javascript - 如何在 JavaScript 中对 Promise 'then' 的结果进行单元测试?

标签 javascript typescript unit-testing jestjs

我正在使用 TypeScript 编写一个利用 AWS SDK 的非常简单的服务。我的 Jest 单元测试正在通过,但覆盖率报告显示“return result.Items”行未被覆盖。谁能告诉这是为什么吗?这是 Jest 中的错误吗?

// service file

/**
 * Gets an array of documents.
 */
function list(tableName) {
  const params = {
    TableName: tableName,
  };
  return docClient
    .scan(params)
    .promise()
    .then((result) => {
      return result.Items;
    });
}

// test file

const stubAwsRequestWithFakeArrayReturn = () => {
  return {
    promise: () => {
      return { then: () => ({ Items: 'fake-value' }) };
    },
  };
};

it(`should call docClient.scan() at least once`, () => {
  const mockAwsCall = jest.fn().mockImplementation(stubAwsRequest);
  aws.docClient.scan = mockAwsCall;
  db.list('fake-table');
  expect(mockAwsCall).toBeCalledTimes(1);
});

it(`should call docClient.scan() with the proper params`, () => {
  const mockAwsCall = jest.fn().mockImplementation(stubAwsRequest);
  aws.docClient.scan = mockAwsCall;
  db.list('fake-table');
  expect(mockAwsCall).toBeCalledWith({
    TableName: 'fake-table',
  });
});

it('should return result.Items out of result', async () => {
  const mockAwsCall = jest
    .fn()
    .mockImplementation(stubAwsRequestWithFakeArrayReturn);
  aws.docClient.get = mockAwsCall;
  const returnValue = await db.get('fake-table', 'fake-id');
  expect(returnValue).toEqual({ Items: 'fake-value' });
});

最佳答案

未覆盖的行是传递给 then 的成功回调。

您的模拟将 then 替换为不接受任何参数且仅返回对象的函数。代码中的回调会在测试期间传递给 then 模拟,但它不会调用回调,因此 Jest 会正确报告您的测试未涵盖该回调。

不要试图返回一个看起来Promise的模拟对象,只需从你的模拟返回一个实际解析的Promise即可:

const stubAwsRequestWithFakeArrayReturn = () => ({
  promise: () => Promise.resolve({ Items: 'fake-value' })
});

...这样then仍将是实际的Promise.prototype.then并且您的回调将按预期被调用。


您还应该等待返回的Promise,以确保在测试完成之前已调用回调:

it(`should call docClient.scan() at least once`, async () => {
  const mockAwsCall = jest.fn().mockImplementation(stubAwsRequest);
  aws.docClient.scan = mockAwsCall;
  await db.list('fake-table');  // await the Promise
  expect(mockAwsCall).toBeCalledTimes(1);
});

it(`should call docClient.scan() with the proper params`, async () => {
  const mockAwsCall = jest.fn().mockImplementation(stubAwsRequest);
  aws.docClient.scan = mockAwsCall;
  await db.list('fake-table');  // await the Promise
  expect(mockAwsCall).toBeCalledWith({
    TableName: 'fake-table',
  });
});

关于javascript - 如何在 JavaScript 中对 Promise 'then' 的结果进行单元测试?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54500259/

相关文章:

javascript - Ajax URL POST 接受本地主机和 IP

javascript - Chrome 显示网页来源而不是应用程序布局。

javascript - 将 In App Browser cordova 插件与 typescript 一起使用

javascript - 在 Typescript 源代码与生成的 JavaScript 上运行测试

调用 EF Core 扩展方法的 c# 单元测试方法

javascript - Stripe 动态支付

javascript - 在一个菜单上指定功能效果的问题

typescript - 为什么 Typescript 允许将 `{a: 1, b: 2}` 分配给类型 `{a: any} | {b: any}` ?

Python模拟对象实例化

maven-surefire-plugin 忽略 pom.xml 中的插件顺序