javascript - 开 Jest 模拟 aws-sdk ReferenceError : Cannot access before initialization

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

Jest 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:初始化前无法访问“mockDynamoDB”

奇怪的是,如果我这样做,我可以避免 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
}

如果有人以前见过这个,或者可以解释为什么第一个例子失败而第二个例子有效,这真的会对我有帮助。谢谢。

最佳答案

这是单元测试解决方案:

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

关于javascript - 开 Jest 模拟 aws-sdk ReferenceError : Cannot access before initialization,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61157392/

相关文章:

node.js - 使用 Node.js 访问 NTLM Api

javascript - 如何使函数等待异步函数在 Node js中解析?

javascript - 在 Javascript 中将变量传递给类方法

javascript - 如何隐藏 'script' HTML 标签?

javascript - Filepond 自定义放置区

javascript - 从 Create-React-App 联系表单发送电子邮件

javascript - 我怎样才能访问 "this"内的项目

javascript - 用磁带 js 模拟文档对象

c# - 为什么 Moq 抛出 "expected Invocation on the mock at least once"。在哪里设置一次,即使它被设置为空?

c# - 我可以模拟 SqlConnection.BeginTransaction c# 吗?