How to test Redux Toolkit Query with Jest and React Testing Library

remarkablemark
2 min readJun 6, 2023

This article goes over how to test RTK Query API with Jest and React Testing Library.

React Testing Library, Redux Toolkit, and Jest

Prerequisites

Install and set up:

Enable jest-fetch-mock in setupTests:

// src/setupTests.ts
import fetchMock from 'jest-fetch-mock';

fetchMock.enableMocks();

We’ll be testing RTK Query’s createApi example. This means the auto-generated React hook is exported from api.ts:

// src/api.ts
export const { useGetPokemonByNameQuery } = pokemonApi;

Test

Create api.test.tsx:

touch api.test.tsx

Create an empty test:

it('renders hook', () => {
// ...
});

Use renderHook to render the hook:

import { useGetPokemonByNameQuery } from './api';

it('renders hook', () => {
renderHook(() => useGetPokemonByNameQuery('pikachu'));
});

The test should fail with the error:

Error: could not find react-redux context value; please ensure the component is wrapped in a <Provider>

Create a wrapper component using the Redux store:

// ...
import { store } from './store';
import { Provider } from 'react-redux';
import type { ReactNode } from 'react';

function Wrapper(props: { children: ReactNode }) {
return <Provider store={store}>{props.children}</Provider>;
}

it('renders hook', () => {
renderHook(() => useGetPokemonByNameQuery('pikachu'), { wrapper: Wrapper });
});

The test should now pass.

Mock the fetch call in beforeAll:

const data = {};

beforeAll(() => {
fetchMock.mockOnceIf('https://pokeapi.co/api/v2/pokemon/pikachu', () =>
Promise.resolve({
status: 200,
body: JSON.stringify({ data }),
})
);
});

Assert that the hook result is correct:

it('renders hook', () => {
const { result } = renderHook(() => useGetPokemonByNameQuery('pikachu'), {
wrapper: Wrapper,
});

expect(result.current).toMatchObject({
status: 'pending',
endpointName: 'getPokemonByName',
isLoading: true,
isSuccess: false,
isError: false,
isFetching: true,
});
});

Assert that fetchMock is called:

it('renders hook', () => {
// ...
expect(fetchMock).toBeCalled();
});

But the test should fail. This is because we need to use waitFor to wait for the request to finish:

it('renders hook', async () => {
// ...
await waitFor(() => expect(result.current.isSuccess).toBe(true));
expect(fetchMock).toBeCalledTimes(1);
});

The test should pass again.

Finally, assert that the updated hook result is correct:

it('renders hook', async () => {
// ...
expect(result.current).toMatchObject({
status: 'fulfilled',
endpointName: 'getPokemonByName',
data: {},
isLoading: false,
isSuccess: true,
isError: false,
currentData: {},
isFetching: false,
});
});

Demo

See CodeSandbox:

--

--