Jest - testing createAsyncThunk

Viewed 5242

I'm currently having some trouble testing my createAsyncThunk function.

Basically the function is:

const myFunc = createAsyncThunk('returns ID', async (nameAndEmail) => {
  const response = await axios.post('/backendroute', nameAndEmail);

  return response.data.id;
};

So this function will send the name and email to the backend which returns an ID.

My testing is currently:

test('returns ID when myFunc is called', async () => {
  const nameAndEmail = {
    name: 'John Smith',
    email: '123@123.com'
  };

  const mockThunk = store.dispatch(myFunc(nameAndEmail));

  expect(mockThunk).toHaveBeenCalledWith(nameAndEmail);
});

The problem is that when I test this, the received value is:

Matcher error: received value must be a mock or spy function
{"abort": [Function abort], "arg": {"email": "123@123.com", "name": "John Smith"}, "requestId": "123456789"}

Could anyone please advise what I'm doing wrong?

1 Answers

You should create a store for testing. After dispatching the asynchronous thunk, assert the value of the final state. Use jest.spyOn() to mock axios.post() method and its returned value.

E.g.

thunk.ts:

import { createAsyncThunk } from '@reduxjs/toolkit';
import axios from 'axios';

const myFunc = createAsyncThunk<string, { name: string; email: string }>('returns ID', async (nameAndEmail) => {
  const response = await axios.post('/backendroute', nameAndEmail);
  return response.data.id;
});

export { myFunc };

thunk.test.ts:

import { myFunc } from './thunk';
import { configureStore } from '@reduxjs/toolkit';
import axios from 'axios';

describe('67087596', () => {
  it('should pass', async () => {
    const nameAndEmail = {
      name: 'John Smith',
      email: '123@123.com',
    };
    const postSpy = jest.spyOn(axios, 'post').mockResolvedValueOnce({ data: { id: '1' } });
    const store = configureStore({
      reducer: function (state = '', action) {
        switch (action.type) {
          case 'returns ID/fulfilled':
            return action.payload;
          default:
            return state;
        }
      },
    });
    await store.dispatch(myFunc(nameAndEmail));
    expect(postSpy).toBeCalledWith('/backendroute', nameAndEmail);
    const state = store.getState();
    expect(state).toEqual('1');
  });
});

unit test result:

 PASS  examples/67087596/thunk.test.ts (11.099 s)
  67087596
    ✓ should pass (7 ms)

----------|---------|----------|---------|---------|-------------------
File      | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s 
----------|---------|----------|---------|---------|-------------------
All files |     100 |      100 |     100 |     100 |                   
 thunk.ts |     100 |      100 |     100 |     100 |                   
----------|---------|----------|---------|---------|-------------------
Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        13.071 s
Related