How do I test axios in Jest?
Solution 1
I used axios-mock-adapter. In this case the service is described in ./chatbot. In the mock adapter you specify what to return when the API endpoint is consumed.
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();
});
});
});
You can see it the whole example here:
Service: https://github.com/lnolazco/hutoma-test/blob/master/src/services/chatbot.js
Test: https://github.com/lnolazco/hutoma-test/blob/master/src/services/chatbot.test.js
Solution 2
Without using any other libraries:
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({ ... }));
// ...
});
It is possible to specify the response code:
axios.get.mockImplementation(() => Promise.resolve({ status: 200, data: {...} }));
It is possible to change the mock based on the parameters:
axios.get.mockImplementation((url) => {
if (url === 'www.example.com') {
return Promise.resolve({ data: {...} });
} else {
//...
}
});
Jest v23 introduced some syntactic sugar for mocking Promises:
axios.get.mockImplementation(() => Promise.resolve({ data: {...} }));
It can be simplified to
axios.get.mockResolvedValue({ data: {...} });
There is also an equivalent for rejected promises: mockRejectedValue
.
Further Reading:
- Jest mocking documentation
- A GitHub discussion that explains about the scope of the
jest.mock("axios")
line. - A related question which addresses applying the techniques above to Axios request interceptors.
- Using jest functions like
mockImplementation
in TypeScript: Typescript and Jest: Avoiding type errors on mocked functions
Solution 3
I could do that following the steps:
- Create a folder __mocks__/ (as pointed by @Januartha comment)
- Implement an
axios.js
mock file - Use my implemented module on test
The mock will happen automatically
Example of the mock module:
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;
})
};
Solution 4
I've done this with nock, like so:
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...
})
})
Solution 5
Look at this
- The function to test
album.js
const fetchAlbum = function () {
return axios
.get("https://jsonplaceholder.typicode.com/albums/2")
.then((response) => {
return response.data;
});
};
- The test
album.test.js
const axios = require("axios");
const { fetchAlbum } = require("../utils.js");
jest.mock("axios");
test("mock axios get function", async () => {
expect.assertions(1);
const album = {
userId: 1,
id: 2,
title: "sunt qui excepturi placeat culpa",
};
const payload = { data: album };
// Now mock axios get method
axios.get = jest.fn().mockResolvedValue(payload);
await expect(fetchAlbum()).resolves.toEqual(album);
});
Adear
Hey, Im a React js and Java developer currently working on clearhub.tech. I'm currently resifting my focus on the back end to node js due to my stronger knowledge of javascript
Updated on January 17, 2022Comments
-
Adear over 2 years
I have this action in React:
export function fetchPosts() { const request = axios.get(`${WORDPRESS_URL}`); return { type: FETCH_POSTS, payload: request } }
How do I test Axios in this case?
Jest has this use case on their site for asynchronous code where they use a mock function, but can I do this with Axios?
Reference: An Async Example
I have done this so far to test that it is returning the correct type:
it('should dispatch actions with the correct type', () => { store.dispatch(fetchPosts()); let action = store.getActions(); expect(action[0].type).toBe(FETCH_POSTS); });
How can I pass in mock data and test that it returns?
-
Adear almost 7 yearsI did try this but i seems that axios does not play well with nock.github.com/node-nock/nock/issues/699 but thank you for your help none the less
-
Kermit_ice_tea over 6 yearsHow did you use the localStorageMock
-
vapurrmaid over 6 years@Kermit_ice_tea
src/setupTests.js
is documented in create-react-app as a global setup for jest/enzyme testing. In that file I created an object that I arbitrarily calledlocalStorageMock
with dummy functions (getItem, setItem). The magic is at the bottom where I setglobal.localStorage
equal to this object. I could've done this in one line instead of naming the object localStorageMock. The purpose of this entire setup was to simply avoid any code dealing with localstorage from breaking during tests. -
Amadeu Cavalcante Filho almost 6 yearsHi @shorif2000 I implemented it here github.com/vspedr/movile-messaging/pull/8/files
-
Januartha almost 6 yearswriting manual mocks inside mocks is not a good practice as the manual mocks documentation says to writing manual mocks inside __mocks__
-
Amadeu Cavalcante Filho almost 6 years@Januartha sorry, for my mistype. I'm gonna to correct it here. I typed on the response "____mock___" and it put my word as bold. Sorry
-
Januartha almost 6 years@AmadeuCavalcanteFilho ah sure, no problem :)
-
Máxima Alekz about 3 yearsWhat if I dont want to mock axios instead, and want it to make a real request?
-
pravindot17 almost 3 yearsnock is the best way to handle http calls in tests
-
Slobodan Krasavčević over 2 yearsReally nice answer, thank you!
-
Brent almost 2 years@MáximaAlekz, I believe for unit tests, you shouldn't make actual API calls. You should always mock.
-
Janac Meena almost 2 yearsIn typescript, there is no
mockImplementation
property. Any suggestions? -
A Jar of Clay almost 2 years@JanacMeena good question; I've added a link (final bullet point) to address this
-
Fiddle Freak almost 2 years@MáximaAlekz Real axios calls performing real CRUD on a backend should be used for end-to-end tests, not a unit tests.
-
Fiddle Freak almost 2 yearsIn the link you provided, I'm getting the same error as Safa Alai
TypeError: mockedAxios.get.mockImplementation is not a function
-
Máxima Alekz almost 2 yearsI don't want to sound rude, but fetchAlbum is NOT being exported, so test will fail