Mock axios with Jest and React Testing Library in Typescript (React)

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 ?

Is that a YES ?

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;
}
Nice and easy right ?

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 💃

Wohoooo 👏👏👏

Software Engineer | Musician | Illustrator

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store