Node.js 和西农开玩笑

Node.js 和西农开玩笑,node.js,aws-sdk,sinon,amazon-ses,aws-sdk-mock,Node.js,Aws Sdk,Sinon,Amazon Ses,Aws Sdk Mock,我试图用西农来模拟SES,但面临以下错误。尝试使用aws sdk模拟,但不起作用 Error: TypeError: Cannot stub non-existent own property sendEmail 测试类的代码段: import * as AWS from 'aws-sdk'; const sandbox = sinon.createSandbox(); sandbox.stub(AWS.SES, 'sendEmail').returns({promise: () =>

我试图用西农来模拟SES,但面临以下错误。尝试使用aws sdk模拟,但不起作用

Error: TypeError: Cannot stub non-existent own property sendEmail
测试类的代码段:

import * as AWS from 'aws-sdk';

const sandbox = sinon.createSandbox();
sandbox.stub(AWS.SES, 'sendEmail').returns({promise: () => true});
实际等级:

import * as AWS from 'aws-sdk';
import * as _ from 'lodash';    

export async function sendAlertMailOnFailure(status:any)
{   
    // load AWS SES
    var ses = new AWS.SES();   
    const params = {
        Destination: {
          ToAddresses: <to_address>
        },
        Message: {...},    
        Source: <sender_address>
      }
      ses.sendEmail(params, (err, data) => {
        if (err) {
          log.error("Error sending mail::");
          log.error(err, err.stack);
        }
      })
}
import*作为AWS从“AWS sdk”导入;
从“lodash”导入*as uuu;
导出异步函数sendAlertMailOnFailure(状态:任意)
{   
//加载AWS SES
var ses=新的AWS.ses();
常量参数={
目的地:{
地址:
},
消息:{…},
资料来源:
}
ses.sendEmail(参数,(错误,数据)=>{
如果(错误){
log.error(“发送邮件时出错::”;
log.error(err,err.stack);
}
})
}

有没有办法用Sinon或aws sdk mock模拟SES?

您需要在
aws
中使用
prototype
来存根它:

import AWS from 'aws-sdk';

const sandbox = sinon.createSandbox();
sandbox.stub(AWS.prototype, 'SES').returns({
  sendEmail: () => {
    return true;
  }
});

该错误似乎表明,
AWS
正在作为
未定义的
导入

可能是您的ES6编译器没有自动转换这一行:

import AWS from 'aws-sdk';
…将
aws sdk中的所有内容导入
aws

将其更改为:

import * as AWS from 'aws-sdk';
…这可能会解决问题



(免责声明:我无法在使用
Babel
v7编译并自动处理任何一种方法的环境中重现错误)

使用require&不使用prototype。这是我模仿DynamoDB的作品

const aws = require('aws-sdk');
const sinon = require('sinon');

const sandbox = sinon.createSandbox();

this.awsStub = sandbox.stub(aws, 'DynamoDB').returns({
  query: function() {
    return {
      promise: function() {
        return {
          Items: []
        };
      }
    };
  }
});
软件包

“aws sdk”:“^2.453.0”


“sinon”:“^7.3.2”

我在这里的回答不是针对
SES
的直接解决方案,但它是我用于模拟
DynamoDB.DocumentClient
SQS
的有效解决方案。也许您可以将我的工作示例改编为单元测试中的
SES
和其他
awsdk
客户端

我只是花了几个小时试图让AWS SQS模拟工作,而没有求助于在函数中导入
AWS sdk
客户端的
AWS sdk模拟
要求

AWS.DynamoDB.DocumentClient
的模拟非常简单,但是
AWS.SQS
模拟让我难堪,直到我遇到使用建议

My lambda将坏消息移动到SQS FailQueue(而不是让lambda失败并将消息返回到常规队列进行重试,然后在maxRetries之后返回DeadLetterQueue)。模拟以下SQS方法所需的单元测试:

  • SQS.getQueueUrl
  • SQS.sendMessage
  • SQS.deleteMessage
我将尽量使示例代码简洁,同时仍包括所有相关部分:

我的AWS Lambda(index.js)的片段:

精简的Lambda事件记录(event.json)

简化单元测试文件(test/index.test.js):


通过执行以下操作,我可以使用awk sdk mock:

测试班

const AWSMock = require('aws-sdk-mock');
const AWS = require('aws-sdk');
AWSMock.setSDKInstance(AWS);

...

    AWSMock.mock('SES', 'sendRawEmail', mockSendEmail);
// call method that needs to mock send an email goes below
    sendEmail(to, from, subject, body, callback);

function mockSendEmail(params, callback) {
    console.log('mock email');
    return callback({
        MessageId: '1234567',
    });
}
实际类

const aws = require('aws-sdk');
const nodemailer = require('nodemailer');


function sendEmail(to, from, subject, body, callback) {
    let addresses = to;
    if (!Array.isArray(addresses)) {
        addresses = [addresses];
    }
    let replyTo = [];
    if (from) {
        replyTo.push(from);
    }

    let data = {
        to: addresses,
        replyTo,
        subject,
        text: body,
    };

    nodemailer.createTransport({ SES: new aws.SES({ apiVersion: '2010-12-01' }) }).sendMail(data, callback);
}

在使用AWS SESGot的位置显示业务逻辑代码错误:TypeError:无法读取未定义的属性“prototype”安装了AWS sdk吗?
AWS sdk
?是。它已经安装好了。使用DynamoDB,它工作得很好。>>stub(DynamoDB.DocumentClient.prototype,'update')。返回({promise:()=>true});错误:正在尝试存根未定义此错误的属性“SES”>>类型错误:无法存根不存在的自有属性SES。尝试使用aws sdk mock,但它不起作用并调用原始方法。在我的示例中,Lambda是index.js,它具有module.exports,包括处理程序函数。在测试文件中,
const lambda=rewire('../index')
是重新布线的lambda,使用LambdaTester进行测试
const AWS = require('aws-sdk');
const expect = require('chai').expect;
const LamdbaTester = require('lambda-tester');
const rewire = require('rewire');
const sinon = require('sinon');

const event = require('./event');
const lambda = rewire('../index');

let sinonSandbox;

function mockGoodSqsMove() {
    const promiseStubSqs = sinonSandbox.stub().resolves({});
    const sqsMock = {
        getQueueUrl: () => ({ promise: sinonSandbox.stub().resolves({ QueueUrl: 'queue-url' }) }),
        sendMessage: () => ({ promise: promiseStubSqs }),
        deleteMessage: () => ({ promise: promiseStubSqs })
    }
    lambda.__set__('sqs', sqsMock);
}

describe('handler', function () {
    beforeEach(() => {
        sinonSandbox = sinon.createSandbox();
    });

    afterEach(() => {
        sinonSandbox.restore();
    });

    describe('when SQS message is in dedupe cache', function () {
        beforeEach(() => {
            // mock SQS
            mockGoodSqsMove();
            // mock DynamoDBClient
            const promiseStub = sinonSandbox.stub().resolves({'Item': 'something'});
            sinonSandbox.stub(AWS.DynamoDB.DocumentClient.prototype, 'get').returns({ promise: promiseStub });
        });

        it('should return an error for a duplicate message', function () {
            return LamdbaTester(lambda.handler)
                .event(event.valid)
                .expectReject((err, additional) => {
                    expect(err).to.have.property('message', 'Duplicate message: {"Item":"something"}');
                });
        });
    });
});
const AWSMock = require('aws-sdk-mock');
const AWS = require('aws-sdk');
AWSMock.setSDKInstance(AWS);

...

    AWSMock.mock('SES', 'sendRawEmail', mockSendEmail);
// call method that needs to mock send an email goes below
    sendEmail(to, from, subject, body, callback);

function mockSendEmail(params, callback) {
    console.log('mock email');
    return callback({
        MessageId: '1234567',
    });
}
const aws = require('aws-sdk');
const nodemailer = require('nodemailer');


function sendEmail(to, from, subject, body, callback) {
    let addresses = to;
    if (!Array.isArray(addresses)) {
        addresses = [addresses];
    }
    let replyTo = [];
    if (from) {
        replyTo.push(from);
    }

    let data = {
        to: addresses,
        replyTo,
        subject,
        text: body,
    };

    nodemailer.createTransport({ SES: new aws.SES({ apiVersion: '2010-12-01' }) }).sendMail(data, callback);
}
const AWS = require('aws-sdk');
...
const sandbox = sinon.createSandbox();
sandbox.stub(AWS, 'SES').returns({
    sendRawEmail: () => {
        console.log("My sendRawEmail");
        return {
            promise: function () {
                return {
                    MessageId: '987654321'
                };
            }
        };
    }
});
let ses = new AWS.SES({ region: 'us-east-1' });
let result = ses.sendRawEmail(params).promise();