如何在 Jest 的 react-native 中使用模拟的 fetch() 对 API 调用进行单元测试
How to unit test API calls with mocked fetch() in react-native with Jest
在 React Native 中,我使用 fetch
来执行网络请求,但是 fetch
不是明确要求的模块,因此在 Jest 中似乎无法模拟。
即使尝试在测试中调用使用 fetch
的方法也会导致:
ReferenceError: fetch is not defined
有没有办法在 Jest 的 React Native 中测试这样的 API 请求?
在您的测试用例中,您可以使用 Jest 的模拟来模拟您想要的任何函数:
fetch = jest.fn(() => Promise.resolve());
此方法仅适用于基于承诺的测试用例(请参阅 Jest 文档中的 pit
)。
至于 fetch
是一个异步函数,您需要使用 pit
运行 所有测试(阅读有关异步测试的更多信息 here)。
您可以使用 jest-fetch-mock npm 包覆盖全局获取对象,而不是滚动您自己的模拟。该软件包允许您设置虚假响应并验证发送的请求。请参阅 link 以获取大量使用示例。
模拟全局 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 : {};
},
});
});
});
};
上面的辅助方法可以随意修改 :-) 希望对大家有帮助
我通过添加 isomorphic-fetch
.
解决了这个问题
$ npm install --save isomorphic-fetch
并像
一样使用它
import fetch from 'isomorphic-fetch';
...
fetch('http://foo.com');
whatwg-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();
});
假设你想测试 resolve 和 reject 案例,为此你首先模拟获取行为,然后使用 Jest 的 rejects 解决方法与断言块
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),
})
})
由于将 fetch-mock 与 jest 一起使用时出现问题,我发布了 fetch-mock-jest. It basically gives the full fetch-mock api,但带有一些 jest 特定的助手,并且开箱即用,无需进行任何棘手的接线你自己
在 React Native 中,我使用 fetch
来执行网络请求,但是 fetch
不是明确要求的模块,因此在 Jest 中似乎无法模拟。
即使尝试在测试中调用使用 fetch
的方法也会导致:
ReferenceError: fetch is not defined
有没有办法在 Jest 的 React Native 中测试这样的 API 请求?
在您的测试用例中,您可以使用 Jest 的模拟来模拟您想要的任何函数:
fetch = jest.fn(() => Promise.resolve());
此方法仅适用于基于承诺的测试用例(请参阅 Jest 文档中的 pit
)。
至于 fetch
是一个异步函数,您需要使用 pit
运行 所有测试(阅读有关异步测试的更多信息 here)。
您可以使用 jest-fetch-mock npm 包覆盖全局获取对象,而不是滚动您自己的模拟。该软件包允许您设置虚假响应并验证发送的请求。请参阅 link 以获取大量使用示例。
模拟全局 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 : {};
},
});
});
});
};
上面的辅助方法可以随意修改 :-) 希望对大家有帮助
我通过添加 isomorphic-fetch
.
$ npm install --save isomorphic-fetch
并像
一样使用它import fetch from 'isomorphic-fetch';
...
fetch('http://foo.com');
whatwg-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();
});
假设你想测试 resolve 和 reject 案例,为此你首先模拟获取行为,然后使用 Jest 的 rejects 解决方法与断言块
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),
})
})
由于将 fetch-mock 与 jest 一起使用时出现问题,我发布了 fetch-mock-jest. It basically gives the full fetch-mock api,但带有一些 jest 特定的助手,并且开箱即用,无需进行任何棘手的接线你自己