node.js - 用 Jest 模拟 AWS SES

标签 node.js unit-testing jestjs aws-sdk aws-sdk-nodejs

我试图在 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) 的单元测试解决方案, 模拟 aws-sdk/clients/ses模块,SES类及其方法。

例如。
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  stackoverflow/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

关于node.js - 用 Jest 模拟 AWS SES,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61491519/

相关文章:

javascript - babel-node 安装 "Only RSA and DSA public keys are allowed"

javascript - 是否可以从node.js中的异步函数返回值?

node.js - 将图像附加到现有 PDF 的正确位置

c# - 对使用文件系统的类进行单元测试

c# - 如何获取测试用例描述?

javascript - Jasmine 无法实例化 Angular 模块?

javascript - 开 Jest : Mocking navigator. 存储.坚持

url - Heroku + Node.js : How to use urls with umlauts?

typescript - 在 Jest 中,我如何对订阅 observable 的方法进行单元测试

reactjs - 用 Jest 测试 Sentry