在笑话模拟模块工厂嘲笑诺言

时间:2019-10-01 22:01:06

标签: javascript unit-testing jestjs

我正在编写一些单元测试,需要从文件中模拟命名的导出,但是当导出是一个返回promise的函数时,它似乎不起作用。

例如,我有一个位于lib/api.js的模块,该模块导出一个名为getFoo的函数,该函数本身返回axios.get('/ foo')。

在测试中,我想将getFoo的返回值模拟为foo有效负载的可解析承诺,因此我使用模块工厂进行模拟:

import * as api from 'lib/api';
jest.mock('lib/api', () => ({
  getFoo: jest.fn(() => Promise.resolve('foo')),
});

然后在我的测试中,我想断言getFoo是链式承诺的较大过程的一部分。

it('getBar should call getFoo', () => {
  return getBar().then(() => {
    expect(api.getFoo).toHaveBeenCalled();
  });
})

我在这里得到的错误是cannot read property 'then' of undefined,好像在模拟模块工厂中使用的开玩笑的函数没有返回诺言。

如果getFoo的返回值不是一个承诺,它将按预期工作。如果我使用jest.fn()作为getFoo的值,然后在测试本身中模拟实现...

it('getBar should call getFoo', () => {
  api.getFoo.mockImplementation(() => Promise.resolve("foo"));
  return getBar().then(() => {
    expect(api.getFoo).toHaveBeenCalled();
  });
})

...然后它起作用了。我的理解是jest.fn(()=> {})应该只是定义实现的一种较短的方法,所以我不确定为什么会出现错误。任何帮助表示赞赏。

谢谢。

更多信息:

lib/api看起来像这样...

import axios from 'axios';

export const getFoo = (host: string, accessToken: string): Promise<{}> =>
  axios.get(`${host}/foo`, {
    headers: {
      Authorization: `Bearer ${accessToken}`,
      'Content-Type': 'application/json',
    }
  })
  // return foo
  .then((response) => response.data)
  .catch(() => {
    throw new Error('Failed to load foo');
  });

当我在测试运行时控制台记录模拟的getFoo函数时,它显示为...

getFoo function mockConstructor() {
  return fn.apply(this, arguments);                                                                         }

1 个答案:

答案 0 :(得分:0)

第一件事,您需要在导入之前对其进行模拟:

jest.mock('lib/api');

import * as api from 'lib/api';