首页 > 解决方案 > 开玩笑模拟 aws-sdk ReferenceError:在初始化之前无法访问

问题描述

开玩笑 25.3.0

我试图在我的单元测试中模拟 DynamoDB 依赖项,如下所示:

const { findById } = require('./mymodule');

const mockDynamoDB = { getItem: jest.fn() };
jest.mock('aws-sdk', () => ({
  DynamoDB: jest.fn(() => mockDynamoDB)
}));

describe('.', () => {
  it('..', () => {
    findById('test');
    expect(mockDynamoDB.getItem).toBeCalledWith({
      TableName: 'table-name',
      Key: {
        id: { S: 'test' }
      }
    });
  });
});

不幸的是,当我这样做时,我收到以下错误:

ReferenceError: Cannot access 'mockDynamoDB' before initialization

奇怪的是,如果我这样做,我可以避免ReferenceError

const mockGetItem = { promise: jest.fn() };
jest.mock('aws-sdk', () => ({
  DynamoDB: jest.fn(() => ({
    getItem: jest.fn(() => mockGetItem)
  })
}));

但这不适合我的测试,因为我无法验证传递给getItem函数的参数。

实际测试的代码相当简单,看起来像这样:

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

const dynamodb = new AWS.DynamoDB({apiVersion: '2012-08-10'});

const toRecord = (item) => ({
  id: item.id.S,
  name: item.name.S
});

const findById = (id) => (
  dynamodb.getItem({
    TableName: 'table-name',
    Key: {
      id: { S: id }
    }
  }).promise()
    .then(result => toRecord(result.Item))
    .catch(error => console.log(error)
);

module.exports = {
  findById
}

如果有人以前见过这个,或者可以阐明为什么第一个示例失败而第二个有效,它真的会帮助我。谢谢你。

标签: javascriptnode.jsunit-testingjestjsaws-sdk

解决方案


这是单元测试解决方案:

index.js

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

const dynamodb = new AWS.DynamoDB({ apiVersion: '2012-08-10' });
const toRecord = (item) => ({
  id: item.id.S,
  name: item.name.S,
});

const findById = (id) =>
  dynamodb
    .getItem({
      TableName: 'table-name',
      Key: {
        id: { S: id },
      },
    })
    .promise()
    .then((result) => toRecord(result.Item))
    .catch((error) => console.log(error));

module.exports = { findById };

index.test.js

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

jest.mock('aws-sdk', () => {
  const mDynamoDB = { getItem: jest.fn().mockReturnThis(), promise: jest.fn() };
  return { DynamoDB: jest.fn(() => mDynamoDB) };
});

describe('61157392', () => {
  let dynamodb;
  beforeAll(() => {
    dynamodb = new AWS.DynamoDB();
  });
  afterAll(() => {
    jest.resetAllMocks();
  });
  it('should pass', async () => {
    dynamodb.getItem().promise.mockResolvedValueOnce({
      Item: {
        id: { S: '1' },
        name: { S: 'a' },
      },
    });
    const actual = await findById('1');
    expect(actual).toEqual({ id: '1', name: 'a' });
    expect(dynamodb.getItem).toBeCalledWith({
      TableName: 'table-name',
      Key: {
        id: { S: '1' },
      },
    });
    expect(dynamodb.getItem().promise).toBeCalledTimes(1);
  });
});

覆盖率 100% 的单元测试结果:

 PASS  stackoverflow/61157392/index.test.js (8.216s)
  61157392
    ✓ should pass (4ms)

----------|---------|----------|---------|---------|-------------------
File      | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s 
----------|---------|----------|---------|---------|-------------------
All files |   88.89 |      100 |      75 |    87.5 |                   
 index.js |   88.89 |      100 |      75 |    87.5 | 19                
----------|---------|----------|---------|---------|-------------------
Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        9.559s

源代码:https ://github.com/mrdulin/react-apollo-graphql-starter-kit/tree/master/stackoverflow/61157392


推荐阅读