用 Jest 模拟 AWS SES
Mocking AWS SES with Jest
我正在尝试在 Jest 中模拟 AWS SES,但继续出现此超时错误:
Timeout - Async callback was not invoked within the 5000ms timeout specified by jest.setTimeout.Timeout - Async callback was not invoked within the 5000ms timeout specified by jest.setTimeout.Error:
我已经删除了不相关的代码并验证可以正常工作。下面是使用 SES 的代码:
import SES from 'aws-sdk/clients/ses';
try {
/** Initialize SES Class */
const ses = new SES({ apiVersion: '2010-12-01' });
await ses.sendTemplatedEmail(sesEmailParams).promise();
} catch(err) {
return next(internalErrorMessage);
}
这里是使用SES的测试:
import AWS from 'aws-sdk';
test('Should error when ses.sendTemplatedEmail.promise() fails', async (done) => {
const fakeSesPromise = {
promise: jest
.fn()
.mockImplementationOnce(() => Promise.reject(new Error('This is an SES error'))),
};
const fakeSes = {
sendTemplatedEmail: () => {
return fakeSesPromise;
},
};
AWS.SES = jest.fn(() => fakeSes);
await user.forgotPassword(mockRequest, mockResponse, mockNext);
expect(fakeSesPromise).toHaveBeenCalledTimes(1);
expect(mockNext).toHaveBeenCalledWith(internalErrorMessage);
done();
});
我尝试了其他一些建议的方法,但结果相同。我假设它与 aws-sdk
如何使用 .promise()
函数有关。
如有任何帮助,我们将不胜感激!
更新#1:
来自@slideshowp2 的以下解决方案有效,但会抛出此 Typescript 错误:
Property 'mockRejectedValueOnce' does not exist on type '() => Promise<PromiseResult<SendTemplatedEmailResponse, AWSError>>'
对于这一行:
mockSes.sendTemplatedEmail().promise.mockRejectedValueOnce(new Error('This is an SES error'));
要使其正常工作,只需更改此行:
const mockSes = new mockSES();
至:
const mockSes = (new SES() as unknown) as { sendTemplatedEmail: jest.Mock; promise: jest.Mock };
这是使用 jest.mock(moduleName, factory, options)、mock aws-sdk/clients/ses
模块、SES
class 及其方法的单元测试解决方案。
例如
user.js
:
import SES from 'aws-sdk/clients/ses';
const internalErrorMessage = 'internalErrorMessage';
export const user = {
async forgotPassword(req, res, next) {
const sesEmailParams = {
Source: 'Sender Name <sender@recipient.com>',
Destination: {
ToAddresses: [],
},
Template: 'tpl',
TemplateData: 'data',
};
try {
const ses = new SES({ apiVersion: '2010-12-01' });
await ses.sendTemplatedEmail(sesEmailParams).promise();
} catch (err) {
return next(internalErrorMessage);
}
},
};
user.test.js
:
import MockSES from 'aws-sdk/clients/ses';
import { user } from './user';
jest.mock('aws-sdk/clients/ses', () => {
const mSES = {
sendTemplatedEmail: jest.fn().mockReturnThis(),
promise: jest.fn(),
};
return jest.fn(() => mSES);
});
describe('61491519', () => {
test('Should error when ses.sendTemplatedEmail.promise() fails', async () => {
const mSes = new MockSES();
const mError = new Error('This is an SES error');
mSes.sendTemplatedEmail().promise.mockRejectedValueOnce(mError);
const mockRequest = {};
const mockResponse = {};
const mockNext = jest.fn();
await user.forgotPassword(mockRequest, mockResponse, mockNext);
expect(MockSES).toBeCalledWith({ apiVersion: '2010-12-01' });
expect(mSes.sendTemplatedEmail).toBeCalledWith({
Source: 'Sender Name <sender@recipient.com>',
Destination: {
ToAddresses: [],
},
Template: 'tpl',
TemplateData: 'data',
});
expect(mSes.sendTemplatedEmail().promise).toBeCalledTimes(1);
expect(mockNext).toHaveBeenCalledWith('internalErrorMessage');
});
});
100% 覆盖率的单元测试结果:
PASS Whosebug/61491519/user.test.js (10.071s)
61491519
✓ Should error when ses.sendTemplatedEmail.promise() fails (6ms)
----------|---------|----------|---------|---------|-------------------
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s
----------|---------|----------|---------|---------|-------------------
All files | 100 | 100 | 100 | 100 |
user.js | 100 | 100 | 100 | 100 |
----------|---------|----------|---------|---------|-------------------
Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
Snapshots: 0 total
Time: 12.115s
我正在尝试在 Jest 中模拟 AWS SES,但继续出现此超时错误:
Timeout - Async callback was not invoked within the 5000ms timeout specified by jest.setTimeout.Timeout - Async callback was not invoked within the 5000ms timeout specified by jest.setTimeout.Error:
我已经删除了不相关的代码并验证可以正常工作。下面是使用 SES 的代码:
import SES from 'aws-sdk/clients/ses';
try {
/** Initialize SES Class */
const ses = new SES({ apiVersion: '2010-12-01' });
await ses.sendTemplatedEmail(sesEmailParams).promise();
} catch(err) {
return next(internalErrorMessage);
}
这里是使用SES的测试:
import AWS from 'aws-sdk';
test('Should error when ses.sendTemplatedEmail.promise() fails', async (done) => {
const fakeSesPromise = {
promise: jest
.fn()
.mockImplementationOnce(() => Promise.reject(new Error('This is an SES error'))),
};
const fakeSes = {
sendTemplatedEmail: () => {
return fakeSesPromise;
},
};
AWS.SES = jest.fn(() => fakeSes);
await user.forgotPassword(mockRequest, mockResponse, mockNext);
expect(fakeSesPromise).toHaveBeenCalledTimes(1);
expect(mockNext).toHaveBeenCalledWith(internalErrorMessage);
done();
});
我尝试了其他一些建议的方法,但结果相同。我假设它与 aws-sdk
如何使用 .promise()
函数有关。
如有任何帮助,我们将不胜感激!
更新#1:
来自@slideshowp2 的以下解决方案有效,但会抛出此 Typescript 错误:
Property 'mockRejectedValueOnce' does not exist on type '() => Promise<PromiseResult<SendTemplatedEmailResponse, AWSError>>'
对于这一行:
mockSes.sendTemplatedEmail().promise.mockRejectedValueOnce(new Error('This is an SES error'));
要使其正常工作,只需更改此行:
const mockSes = new mockSES();
至:
const mockSes = (new SES() as unknown) as { sendTemplatedEmail: jest.Mock; promise: jest.Mock };
这是使用 jest.mock(moduleName, factory, options)、mock aws-sdk/clients/ses
模块、SES
class 及其方法的单元测试解决方案。
例如
user.js
:
import SES from 'aws-sdk/clients/ses';
const internalErrorMessage = 'internalErrorMessage';
export const user = {
async forgotPassword(req, res, next) {
const sesEmailParams = {
Source: 'Sender Name <sender@recipient.com>',
Destination: {
ToAddresses: [],
},
Template: 'tpl',
TemplateData: 'data',
};
try {
const ses = new SES({ apiVersion: '2010-12-01' });
await ses.sendTemplatedEmail(sesEmailParams).promise();
} catch (err) {
return next(internalErrorMessage);
}
},
};
user.test.js
:
import MockSES from 'aws-sdk/clients/ses';
import { user } from './user';
jest.mock('aws-sdk/clients/ses', () => {
const mSES = {
sendTemplatedEmail: jest.fn().mockReturnThis(),
promise: jest.fn(),
};
return jest.fn(() => mSES);
});
describe('61491519', () => {
test('Should error when ses.sendTemplatedEmail.promise() fails', async () => {
const mSes = new MockSES();
const mError = new Error('This is an SES error');
mSes.sendTemplatedEmail().promise.mockRejectedValueOnce(mError);
const mockRequest = {};
const mockResponse = {};
const mockNext = jest.fn();
await user.forgotPassword(mockRequest, mockResponse, mockNext);
expect(MockSES).toBeCalledWith({ apiVersion: '2010-12-01' });
expect(mSes.sendTemplatedEmail).toBeCalledWith({
Source: 'Sender Name <sender@recipient.com>',
Destination: {
ToAddresses: [],
},
Template: 'tpl',
TemplateData: 'data',
});
expect(mSes.sendTemplatedEmail().promise).toBeCalledTimes(1);
expect(mockNext).toHaveBeenCalledWith('internalErrorMessage');
});
});
100% 覆盖率的单元测试结果:
PASS Whosebug/61491519/user.test.js (10.071s)
61491519
✓ Should error when ses.sendTemplatedEmail.promise() fails (6ms)
----------|---------|----------|---------|---------|-------------------
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s
----------|---------|----------|---------|---------|-------------------
All files | 100 | 100 | 100 | 100 |
user.js | 100 | 100 | 100 | 100 |
----------|---------|----------|---------|---------|-------------------
Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
Snapshots: 0 total
Time: 12.115s