Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
140 views
in Technique[技术] by (71.8m points)

javascript - Jest testing axios / thunk

I'm new in testing and trying to test an asynchronous data fetching. What actions I do wrong. Or how I can testing it? axios.mockResolvedValueOnce(result) says that Property 'mockResolvedValueOnce' does not exist on type 'AxiosStatic'

api.ts

export const createAccount = createAsyncThunk(
    'account/createAccount',
    async (Info: User) => {
        try {
            return await axios.post(APIUrl + 'users.json', Info);
        } catch (err) {
            const { status, errorMessage } = err?.response?.data;
            const error: ErrorResponse = {
                status: status,
                message: errorMessage,
            };

            return error;
        }
    },
);

api.test.ts

import axios from 'axios';
import { createAccount } from '../api';

jest.mock('axios');

describe('user account', () => {
    afterEach(() => {
        jest.restoreAllMocks();
    });
    it('should return data if status code equals 200', async () => {
        const result = {
            status: 200,
            data: {},
        };
        axios.post.mockResolvedValueOnce(result); <-- Property 'mockResolvedValueOnce' does not exist on type 'AxiosStatic'
        const actual = await createAccount({
            id: '1',
            firstName: 'first name',
            lastName: 'last name',
            email: 'email',
            phone: 'phone',
        });
        expect(actual).toEqual({});
        expect(axios).toBeCalledWith({
            method: 'post',
            url: 'http://localhost:3000/',
            headers: { 'content-type': 'application/json' },
            data: { id: '1', firstName: 'first name', lastName: 'last name', email: 'email', phone: 'phone' },
        });
    });

    it('should throw error if status code equals 400', async () => {
        const result = { status: 400, message: jest.fn().mockReturnValue('network') };
    });
});
question from:https://stackoverflow.com/questions/65845191/jest-testing-axios-thunk

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

createAsyncThunk returns a standard Redux thunk action creator. Not the return value of axios.post(). You can find the type of the redux thunk action creator here AsyncThunkAction. So you can create a mocked dispatch function, getState function and pass them to it.

We mocked axios.post method, so we should make assertion for this method to have be called with arguments rather than axios function.

E.g.

api.ts:

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

const APIUrl = 'http://localhost:3000/';

export interface User {}
export interface ErrorResponse {}

export const createAccount = createAsyncThunk('account/createAccount', async (Info: User) => {
  try {
    return await axios.post(APIUrl + 'users.json', Info);
  } catch (err) {
    const { status, errorMessage } = err?.response?.data;
    const error: ErrorResponse = {
      status: status,
      message: errorMessage,
    };

    return error;
  }
});

api.test.ts:

import axios from 'axios';
import { createAccount, ErrorResponse, User } from './api';
import { AsyncThunkAction } from '@reduxjs/toolkit';

jest.mock('axios');

describe('user account', () => {
  afterEach(() => {
    jest.restoreAllMocks();
  });
  it('should return data if status code equals 200', async () => {
    const dispatch = jest.fn();
    const result = {
      status: 200,
      data: {},
    };
    (axios.post as jest.MockedFunction<typeof axios.post>).mockResolvedValueOnce(result);
    const createAccountAsyncThunkAction: AsyncThunkAction<ErrorResponse, User, {}> = createAccount({
      id: '1',
      firstName: 'first name',
      lastName: 'last name',
      email: 'email',
      phone: 'phone',
    });

    const actual = await createAccountAsyncThunkAction(dispatch, () => {}, undefined);
    expect(actual.meta.arg).toEqual({
      id: '1',
      firstName: 'first name',
      lastName: 'last name',
      email: 'email',
      phone: 'phone',
    });
    expect(actual.payload).toEqual({ status: 200, data: {} });
    expect(axios.post).toBeCalledWith('http://localhost:3000/users.json', {
      id: '1',
      firstName: 'first name',
      lastName: 'last name',
      email: 'email',
      phone: 'phone',
    });
  });
});

unit test result:

 PASS  examples/65845191/api.test.ts
  user account
    ? should return data if status code equals 200 (3 ms)

----------|---------|----------|---------|---------|-------------------
File      | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s 
----------|---------|----------|---------|---------|-------------------
All files |      70 |        0 |     100 |   66.67 |                   
 api.ts   |      70 |        0 |     100 |   66.67 | 13-19             
----------|---------|----------|---------|---------|-------------------
Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        3.423 s, estimated 4 s

package versions:

"axios": "^0.21.1",
"jest": "^26.6.3",
"@reduxjs/toolkit": "^1.5.0",

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...