使用通过Jest + node-fetch + fetch-mock进行的抓取来测试库的响应和函数调用

时间:2018-10-06 21:30:09

标签: unit-testing mocking fetch jestjs

我正在编写一个使用fetch的JavaScript / React库。

我正在使用Jest来测试该库,我想要实现的是:

  1. 模拟HTTP请求,以便不发送实际调用并处理答案(模拟后端服务器),因此我使用的是fetch-mock
  2. 测试传递给fetch函数的参数

为了达到第一点,我需要做

fetchMock.post(`${API_URL}/sessions`, {
  body: JSON.stringify({
    token: 'this-is-your-token'
  }),
  status: 201
})

为了达到第二点,我需要做

const spiedFetch = jest.spyOn(global, 'fetch')
// ...
expect(spiedFetch).toHaveBeenCalledTimes(1)

(最后一行在一系列describe()it()内)。

我有一个第一个测试,它确保响应具有token字段,依此类推,而第二个测试是确保fetch被调用一次。

当我运行它们时,第一个通过,然后第二个失败。当我评论fetchMock.post(...)时,第一个失败,第二个通过。

基于此,我认为fetch-mockjest.spyOn不兼容。

问题:

  1. 我是否认为fetch-mockjest.spyOn不兼容?
  2. 如何实现对fetch响应和传递的参数的测试? (我想确保HTTP动词就是这个,并且传递的标头就是那个。)
  3. 我想到的一种方法是按原样使用fetch-mock,但是在我的lib函数上使用jest.spyOn,该函数将嵌入fetch。这样行吗?

更新:我尝试了第3点,它可以正常工作。

1 个答案:

答案 0 :(得分:1)

jest.spyOn replaces the original function with a wrapper

const fetchMock = require('fetch-mock');不会立即更改全局fetch,但是as soon as a function like fetchMock.get被称为it replaces the global fetch

因为它们都可以通过修改全局fetch来工作,所以它们很难一起使用。

事实证明,每次fetchMock.get之类的方法被称为全局fetch时都会被替换,但是如果jest.spyOn被称为之后,则所有此类方法在fetchMock上被调用,则它们实际上都将起作用,因为jest.spyOn将包装并跟踪最终替换的fetch

话虽如此,如果您已经在使用jest.spyOn(global, 'fetch'),则实际上并不需要使用fetch-mock,因为fetch-mock可以访问对{{1 }}。

要直接在通话中断言,您可以access them using fetchMock.calls()

更容易的是在测试结束时simply call fetchMock.done()断言fetch的使用完全符合预期。