用玩笑模拟dynamodb扫描

时间:2019-01-25 07:14:40

标签: node.js mocking jestjs

对于源代码(dynamodb.js):

const AWS = require("aws-sdk"); 
const Promise = require("bluebird");
const client = new AWS.DynamoDB.DocumentClient();
module.exports.db = (method, params) => {
  console.log("access dynamodb ");
  return Promise.fromCallback(cb => client[method](params, cb));
};

使用如下所示的测试(不要模拟Promise.fromCallback):

describe("test", () => {
  const realAWS = require("aws-sdk");
  let fakePromise;
  let fakeDynamo;
  let dbClient;
  beforeAll(function() {
    fakePromise = jest.fn();
    fakeDynamo = {
      get: (params, cb) => {
        fakePromise(params, cb);
      }
    };
    realAWS.DynamoDB.DocumentClient = jest.fn(() => fakeDynamo);
    dbClient = require("../dynamodb");
  });
  test.only("Test successed", done => {
    let result = dbClient.db("get", null);
    console.log("access dynamodb ");
    expect(fakePromise).toHaveBeenCalled();
  });
});

但是当测试调优时,错误却突然发生了:

Timeout - Async callback was not invoked within the 5000ms timeout specified by jest.setTimeout.

有人可以帮助我吗?谢谢!

1 个答案:

答案 0 :(得分:0)

您需要将client.get方法的实现模拟为节点回调样式。这样Promise.fromCallback方法将隐式回调样式变为Promise。

此外,您需要在测试用例中触发回调。这就是为什么出现超时错误的原因。

例如

dynamodb.js

const AWS = require('aws-sdk');
const Promise = require('bluebird');

const client = new AWS.DynamoDB.DocumentClient();

module.exports.db = (method, params) => {
  console.log('access dynamodb');
  return Promise.fromCallback((cb) => client[method](params, cb));
};

dynamodb.test.js

const { db } = require('./dynamodb');
const AWS = require('aws-sdk');

jest.mock('aws-sdk', () => {
  const mClient = { get: jest.fn() };
  const mDynamoDB = {
    DocumentClient: jest.fn(() => mClient),
  };
  return { DynamoDB: mDynamoDB };
});

const mockClient = new AWS.DynamoDB.DocumentClient();

describe('54360588', () => {
  afterAll(() => {
    jest.resetAllMocks();
  });
  it('should pass', async () => {
    mockClient.get.mockImplementationOnce((err, callback) => {
      callback(null, 'fake data');
    });
    const actual = await db('get', null);
    expect(actual).toBe('fake data');
    expect(mockClient.get).toBeCalledWith(null, expect.any(Function));
  });
});

具有覆盖率报告的单元测试结果:

 PASS  src/stackoverflow/54360588/dynamodb.test.js (10.74s)
  54360588
    ✓ should pass (28ms)

  console.log src/stackoverflow/54360588/dynamodb.js:177
    access dynamodb

-------------|----------|----------|----------|----------|-------------------|
File         |  % Stmts | % Branch |  % Funcs |  % Lines | Uncovered Line #s |
-------------|----------|----------|----------|----------|-------------------|
All files    |      100 |      100 |      100 |      100 |                   |
 dynamodb.js |      100 |      100 |      100 |      100 |                   |
-------------|----------|----------|----------|----------|-------------------|
Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        12.636s