开玩笑测试 axios / thunk

时间:2021-01-22 12:27:49

标签: javascript reactjs typescript jestjs enzyme

我刚开始测试并尝试测试异步数据获取。我做错了什么动作。或者我如何测试它? axios.mockResolvedValueOnce(result) 表示 属性 'mockResolvedValueOnce' 不存在于类型 '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') };
    });
});

1 个答案:

答案 0 :(得分:0)

createAsyncThunk 返回一个标准的 Redux thunk 动作创建者。不是 axios.post() 的返回值。您可以在此处找到 redux thunk 动作创建者的类型 AsyncThunkAction。因此,您可以创建一个模拟的 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",