How do I test axios in Jest?
我在React中有这个动作:
1 2 3 4 5 6 7 | export function fetchPosts() { const request = axios.get(`${WORDPRESS_URL}`); return { type: FETCH_POSTS, payload: request } } |
在这种情况下如何测试Axios?
Jest在他们的网站上有一个用于使用仿函数的异步代码的用例,但是我可以使用Axios吗?
参考:异步示例
到目前为止,我已经进行了测试以测试它是否返回了正确的类型:
1 2 3 4 5 | it('should dispatch actions with the correct type', () => { store.dispatch(fetchPosts()); let action = store.getActions(); expect(action[0].type).toBe(FETCH_POSTS); }); |
如何传递模拟数据并测试其返回?
不使用任何其他库:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | import * as axios from"axios"; // Mock out all top level functions, such as get, put, delete and post: jest.mock("axios"); // ... test("good response", () => { axios.get.mockImplementation(() => Promise.resolve({ data: {...} })); // ... }); test("bad response", () => { axios.get.mockImplementation(() => Promise.reject({ ... })); // ... }); |
可以指定响应代码:
1 | axios.get.mockImplementation(() => Promise.resolve({ status: 200, data: {...} })); |
可以根据以下参数更改模拟:
1 2 3 4 5 6 7 | axios.get.mockImplementation((url) => { if (url === 'www.example.com') { return Promise.resolve({ data: {...} }); } else { //... } }); |
Jest v23引入了一些语法糖来嘲笑Promises:
1 | axios.get.mockImplementation(() => Promise.resolve({ data: {...} })); |
可以简化为
1 | axios.get.mockResolvedValue({ data: {...} }); |
被拒绝的承诺也有一个等效项:
进一步阅读:
- 开玩笑的嘲笑文档
-
GitHub上的讨论,它解释了
jest.mock("axios") 行的范围。 - 我的另一个答案是解决将上述技术应用于Axios请求拦截器的问题。
我使用了axios-mock-adapter。
在这种情况下,服务在./chatbot中描述。
在模拟适配器中,您指定使用API??端点时返回的内容。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | import axios from 'axios'; import MockAdapter from 'axios-mock-adapter'; import chatbot from './chatbot'; describe('Chatbot', () => { it('returns data when sendMessage is called', done => { var mock = new MockAdapter(axios); const data = { response: true }; mock.onGet('https://us-central1-hutoma-backend.cloudfunctions.net/chat').reply(200, data); chatbot.sendMessage(0, 'any').then(response => { expect(response).toEqual(data); done(); }); }); }); |
您可以在此处看到整个示例:
服务:
https://github.com/lnolazco/hutoma-test/blob/master/src/services/chatbot.js
测试:
https://github.com/lnolazco/hutoma-test/blob/master/src/services/chatbot.test.js
我可以按照以下步骤进行操作:
模拟将自动发生
模拟模块示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | module.exports = { get: jest.fn((url) => { if (url === '/something') { return Promise.resolve({ data: 'data' }); } }), post: jest.fn((url) => { if (url === '/something') { return Promise.resolve({ data: 'data' }); } if (url === '/something2') { return Promise.resolve({ data: 'data2' }); } }), create: jest.fn(function () { return this; }) }; |
我已经用nock做到了,就像这样:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | import nock from 'nock' import axios from 'axios' import httpAdapter from 'axios/lib/adapters/http' axios.defaults.adapter = httpAdapter describe('foo', () => { it('bar', () => { nock('https://example.com:443') .get('/example') .reply(200, 'some payload') // test... }) }) |
对于那些希望使用axios-mock-adapter来代替Redux文档中的嘲讽示例进行异步测试的人,我成功使用了以下内容:
文件actions.test.js:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | describe('SignInUser', () => { var history = { push: function(str) { expect(str).toEqual('/feed'); } } it('Dispatches authorization', () => { let mock = new MockAdapter(axios); mock.onPost(`${ROOT_URL}/auth/signin`, { email: '[email protected]', password: 'test' }).reply(200, {token: 'testToken' }); const expectedActions = [ { type: types.AUTH_USER } ]; const store = mockStore({ auth: [] }); return store.dispatch(actions.signInUser({ email: '[email protected]', password: 'test', }, history)).then(() => { expect(store.getActions()).toEqual(expectedActions); }); }); |
为了在文件actions / index.js中测试
1 2 3 4 5 6 7 8 9 10 11 12 | export const signInUser = ({ email, password }, history) => async dispatch => { const res = await axios.post(`${ROOT_URL}/auth/signin`, { email, password }) .catch(({ response: { data } }) => { ... }); if (res) { dispatch({ type: AUTH_USER }); // Test verified this localStorage.setItem('token', res.data.token); // Test mocked this history.push('/feed'); // Test mocked this } } |
鉴于这是在开玩笑,因此必须模拟localstorage调用。这在文件src / setupTests.js中:
1 2 3 4 5 6 7 | const localStorageMock = { removeItem: jest.fn(), getItem: jest.fn(), setItem: jest.fn(), clear: jest.fn() }; global.localStorage = localStorageMock; |