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:

--

--