【发布时间】:2016-07-04 08:13:56
【问题描述】:
在 React Native 中,我使用 fetch 来执行网络请求,但是 fetch 不是明确需要的模块,因此在 Jest 中似乎无法模拟。
即使尝试在测试中调用使用fetch 的方法也会导致:
ReferenceError:未定义提取
有没有办法在 Jest 的原生反应中测试此类 API 请求?
【问题讨论】:
标签: unit-testing react-native jestjs
在 React Native 中,我使用 fetch 来执行网络请求,但是 fetch 不是明确需要的模块,因此在 Jest 中似乎无法模拟。
即使尝试在测试中调用使用fetch 的方法也会导致:
ReferenceError:未定义提取
有没有办法在 Jest 的原生反应中测试此类 API 请求?
【问题讨论】:
标签: unit-testing react-native jestjs
在您的测试用例中,您可以使用 Jest 的模拟来模拟您想要的任何功能:
fetch = jest.fn(() => Promise.resolve());
这种方法仅适用于基于 Promise 的测试用例(请参阅 Jest 文档中的 pit)。
就fetch 是一个异步函数而言,您需要使用pit 运行所有测试(阅读有关异步测试的更多信息here)。
【讨论】:
it。
it函数的范围内使用上面的sn-p。
afterEach 来恢复模拟。例如,在describe 的主体中,您可以在const originalFetch = fetch 中运行afterEach,然后在it 中安全地覆盖fetch,如上所示。
您可以使用jest-fetch-mock npm 包覆盖全局提取对象,而不是滚动您自己的模拟。该软件包允许您设置虚假响应并验证发送的请求。有关广泛的使用示例,请参阅该链接。
【讨论】:
matcher 并自动拦截所有 fetch 调用。我不想在单元测试中复制我的 Express 设置,只是为了确保被测试的代码接收到合法的 Response 对象。
另一种模拟全局 fetch 对象的方法:
const mockSuccesfulResponse = (
status = 200,
method = RequestType.GET,
returnBody?: object
) => {
global.fetch = jest.fn().mockImplementationOnce(() => {
return new Promise((resolve, reject) => {
resolve({
ok: true,
status,
json: () => {
return returnBody ? returnBody : {};
},
});
});
});
};
上面的辅助方法可以任意修改 :-) 希望对某人有所帮助
【讨论】:
json: () => Promise.resolve({ ... }) 来确保.then 与await 一起工作。
我通过添加isomorphic-fetch 解决了这个问题。
$ npm install --save isomorphic-fetch
并像使用它
import fetch from 'isomorphic-fetch';
...
fetch('http://foo.com');
whatwg-fetch 也可以工作
【讨论】:
fetch?
正如@ArthurDenture 建议的那样,您可以使用fetch-mock,但您需要安装一些额外的软件包才能使其与React Native 和Jest 一起使用:
$ npm install --save-dev fetch-mock
$ npm install --save-dev babel-plugin-transform-runtime
$ npm install --save-dev babel-preset-env
然后,您可以在测试中模拟获取请求。这是一个例子:
// __tests__/App.test.js
import React from 'react';
import App from '../App';
import fetchMock from 'fetch-mock';
import renderer from 'react-test-renderer';
it('renders without crashing', () => {
fetchMock.mock('*', 'Hello World!');
const rendered = renderer.create(<App />).toJSON();
expect(rendered).toBeTruthy();
});
【讨论】:
假设您想测试解决和拒绝案例,为此您首先模拟获取行为,然后使用 Jest 的 rejects 和 resolves 带有断言块的方法
function fetchTodos() {
return fetch(`${window.location.origin}/todos.json`)
.then(response => response.json())
.catch(error => console.log(error))
}
describe('fetchTodos', () => {
it('returns promise resolving to parsed response', () => {
global.fetch = jest.fn(() => Promise.resolve({ json: () => ''}))
expect(fetchTodos()).resolves.toBe('');
})
it('returns promise handling the error', async () => {
global.fetch = jest.fn(() => Promise.reject(''))
expect(fetchTodos()).rejects.toBe('')
})
})
【讨论】:
如 react-testing-library 文档中所示,您可以使用 jest.spyOn() 函数,该函数仅在下次调用时模拟 fetch 函数。
const fakeUserResponse = {token: 'fake_user_token'}
jest.spyOn(window, 'fetch').mockImplementationOnce(() => {
return Promise.resolve({
json: () => Promise.resolve(fakeUserResponse),
})
})
【讨论】:
window 对象。
由于 jest 使用 fetch-mock 时出现问题,我已发布 fetch-mock-jest。它基本上提供了完整的fetch-mock api,但有一些专门针对 jest 的助手,并且开箱即用,无需自己进行任何棘手的接线
【讨论】: