【问题标题】:Jest testing axios / thunk开玩笑测试 axios / thunk
【发布时间】:2021-02-22 11:47:37
【问题描述】:

我是测试和尝试测试异步数据获取的新手。我做错了什么。或者我如何测试它? axios.mockResolvedValueOnce(result) 表示 “AxiosStatic”类型上不存在属性“mockResolvedValueOnce”

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') };
    });
});

【问题讨论】:

    标签: javascript reactjs typescript jestjs enzyme


    【解决方案1】:

    createAsyncThunk 返回一个标准的 Redux thunk action creator。不是axios.post() 的返回值。你可以在AsyncThunkAction 找到 redux thunk action creator 的类型。因此,您可以创建一个模拟的dispatch 函数、getState 函数并将它们传递给它。

    我们模拟了axios.post 方法,所以我们应该断言这个方法是用参数调用的,而不是axios 函数。

    例如

    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',
        });
      });
    });
    

    单元测试结果:

     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
    

    软件包版本:

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

    【讨论】:

      猜你喜欢
      • 2020-08-16
      • 2018-08-05
      • 1970-01-01
      • 1970-01-01
      • 2021-11-30
      • 1970-01-01
      • 1970-01-01
      • 2020-02-06
      • 2020-03-25
      相关资源
      最近更新 更多