Mock axios with Jest and React Testing Library in Typescript (React)
Have you been using Typescript in your React project lately ? Jest and React Testing Library are your go to tool for writing tests ? And you are having issues trying to test an async method that fetches data from an api using axois ?
Then my friend, you are in right place. I hope this will solve the problem you are facing and you can get that break you’ve been meaning to take.
Let’s get started 👨🏻💻
Scenario
We’re going to write a method that uses Axios to make an HTTP Get request from free JSONPlaceholder api.
If you go to https://jsonplaceholder.typicode.com/todos it will give you a list of todos in the following format:
[
{
"userId": 1,
"id": 1,
"title": "delectus aut autem",
"completed": false
},
{
"userId": 1,
"id": 2,
"title": "quis ut nam facilis et officia qui",
"completed": false
}
]
Inside your ‘src’ folder of the project, create a ‘types’ folder and add ‘index.ts’ file
├── src
│ ├── types
│ │ ├── index.ts
Since we are working with Todo, let’s create a Todo type first.
Todo
// src/types/index.tsexport type Todo = {
userId: number;
id: number;
title: string;
completed: boolean;
}
Now, let’s add the async method that fetches the data from the api. I like to seperate my api methods and keep it under ‘api’ folder like this:
├── src
│ ├── api
│ │ ├── index.spec.ts
│ │ ├── index.ts
Inside ‘index.ts’, add the following code that fetches your todos
// src/api/index.ts
export const getTodos = async (): Promise<Todo[]> => {
try {
const url = 'https://jsonplaceholder.typicode.com/todos';
const resp = await axios.get(url);
if (resp.status !== 200) {
throw new Error('Something went wrong');
}
const data: Todo[] = await resp.data;
return data;
} catch (err) {
throw err;
}
};
Here’s the fun part now. Let’s write a test for this getTodos() method.
Inside index.spec.ts, add the following code. I’ve added comments in the code to explain what is happening.
// src/api/index.spec.ts
import axios, { AxiosResponse } from 'axios';
import { getTodos } from '.';//jest.mock(...) is used to automatically mock the axios module.jest.mock('axios');// Create an object of type of mocked Axios.
const mockedAxios = axios as jest.Mocked<typeof axios>;describe('getTodos()', () => {
test('should return todo list', async () => { //Our desired output
const todos: Todo[] = [
{
userId: 1,
id: 1,
title: 'todo-test-1',
completed: false,
},
{
userId: 2,
id: 2,
title: 'todo-test-2',
completed: true,
},
];
//Prepare the response we want to get from axios
const mockedResponse: AxiosResponse = {
data: todos,
status: 200,
statusText: 'OK',
headers: {},
config: {},
}; // Make the mock return the custom axios response
mockedAxios.get.mockResolvedValueOnce(mockedResponse); expect(axios.get).not.toHaveBeenCalled();
const data = await getTodos();
expect(axios.get).toHaveBeenCalled();
expect(data).toEqual(todos);
});
});
Now, run the test.
PASS src/api/index.spec.ts
getTodos()
✓ should return todo list (3 ms)Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
Snapshots: 0 total
Time: 3.844 s
It passed 🎉🎉🎉 !!!
You have successfully mocked axios in typescript 💃