如何在Create react app中使用JEST测试/模拟API调用

时间:2020-05-29 03:35:33

标签: reactjs testing jestjs axios

您好,我正在尝试在create react应用程序中测试我的异步操作创建者,但我没有足够的信息来解决此问题。这是我第一次测试react中的异步操作。我正在使用axios来获取API和开玩笑的模拟来创建模拟功能。

这里的提取功能:

export async function signUpAPI(userSignupInfo: ILoginSignUpFormParams): Promise<ILoginSignupResponse> {
  const { username, email, password } = userSignupInfo;
  try {
    const res = await axiosInstance.post('/signup', {
      username,
      email,
      password
    });
    return res.data;
  } catch (error) {
    throw error.response.data;
  }
}

这是我的测试:

import * as sessionActions from '../Actions';
import { sessionInitialState } from 'models/Session/sessionInitialState';
import { SessionActionTypes } from '../Types';
import axios from 'axios';
import { signUpAPI } from 'api/sessions';

jest.mock('axios');
const mockedAxios = axios as jest.Mocked<typeof axios>;

describe('Session Action Test', () => {
  describe('async ACTION Test', () => {
    describe('On signup', () => {
      it('should success response on signup', async () => {
        mockedAxios.post.mockResolvedValue({ data: {} });

        const t = await signUpAPI({ username: 'yousir1', password: 'Password1!', email: 'yousir1@gmail.com' });
        console.log(t);
      });
    });
  });
});

这是我遇到的错误,但由于我将其嘲笑为Resolved value而无法理解,但该错误进入了我实际的API调用中的catch块。很奇怪。

enter image description here

1 个答案:

答案 0 :(得分:0)

花了一些时间来得到它,但我终于想通了。

所以我有这个文件夹结构:

src
├── api
│   └── sessions.ts
├── assets
├── components
├── helper
│   └── sessionSetup.ts
├── index.css
├── index.tsx
├── interfaces
├── lib
│   ├── __mocks__   <<-- you have to create a mock like this first----------
│   │   └── api.ts
│   ├── axios.instance.ts
│   └── axios.interceptors.ts
├── models
├── react-app-env.d.ts
├── routes
├── serviceWorker.ts
├── setupTests.ts
└── store
    ├── root
    ├── session
    │   ├── Actions.ts
    │   ├── Reducers.ts
    │   ├── Selectors.ts
    │   ├── Types.ts
    │   └── test
    │       ├── session.action.test.ts
    │       └── session.reducer.test.ts
    └── user
        ├── Actions.ts
        ├── Reducers.ts
        ├── Selectors.ts
        ├── Types.ts
        └── test
            ├── user.action.test.ts
            └── user.reducer.test.ts

然后在__mock__文件夹中,我有这个。这将模拟我的“ POST”单个API

export default {
  post: jest.fn(() =>
    Promise.resolve({
      data: {}
    })
  )
};

因为我使用的是axios实例,例如:

import axios from 'axios';

const axiosInstance = axios.create({
  baseURL: process.env.REACT_APP_BASE_API_URL
});

export default axiosInstance;

然后在我的API文件夹中使用它,例如:

import axiosInstance from '../lib/axios.instance';
import { ILoginSignupResponse, ILoginSignUpFormParams } from 'interfaces/session';

export async function signUpAPI(userSignupInfo: ILoginSignUpFormParams): Promise<ILoginSignupResponse> {
  const { username, email, password } = userSignupInfo;
  try {
    const res = await axiosInstance.post('/signup', {
      username,
      email,
      password
    });
    return res.data;
  } catch (error) {
    throw error.response.data;
  }
}

然后我必须像这样设置测试:

import * as sessionActions from '../Actions';
import { sessionInitialState } from 'models/Session/sessionInitialState';
import { SessionActionTypes } from '../Types';
import axios from 'axios';
import { signUpAPI } from 'api/sessions';
import axiosInstance from 'lib/axios.instance';

jest.mock('../../../lib/axios.instance.ts');
const mockedAxios = axiosInstance as jest.Mocked<typeof axiosInstance>;

describe('Session Action Test', () => {
  describe('async ACTION Test', () => {
    describe('On signup', () => {
      it('should success response on signup', async () => {
        mockedAxios.post.mockImplementationOnce(() => Promise.resolve({ data: { foo: 'bar' } }));

        const t = await signUpAPI({ username: 'yousir1', password: 'Password1!', email: 'yousir1@gmail.com' });
        console.log(t);
      });
    });
  });
});

jest.mock()将转到模拟文件夹的路径。然后,我可以使用mockedAxios变量来获取__mock__/api.ts文件中的所有属性,并通过给它一个Promise来测试我的API。 t变量的返回值将是您放入Promise.resolve方法中的值。