how to jest test an async action with axios in react?

心不动则不痛 提交于 2021-01-28 01:41:14

问题


I have an action-generator register.js:

import { REGISTER_SUCCESS, REGISTER_FAIL } from "./types";
import axios from "axios";

export const register = (formData) => async (dispatch) => {
  const { name, email, password } = formData;
  const configRegister = {
    method: "post",
    url: "/api/users",
    headers: { "Content-Type": "application/json" },
    data: { name, email, password },
  };
  try {
    const res = await axios(configRegister);
    const token = res.data.token;
    dispatch({
      type: REGISTER_SUCCESS,
      payload: {
        token,
        isAuthenticated: true,
        loading: false,
      },
    });
  } catch (err) {
    console.error(err);
    dispatch({
      type: REGISTER_FAIL,
      payload: {
        token: null,
        isAuthenticated: false,
        loading: true,
      },
    });
  }
}; 

the endpoint /api/users returns {token:'a_token_string'} on being successful.

How should i test this action-generator using jest ?

I tried doing this, register.test.js :-

import {
  REGISTER_SUCCESS,
} from "./types";
import thunk from "redux-thunk";
import configureMockStore from "redux-mock-store";
import axios from "axios";

jest.mock("axios");
    
/** mock-store */
const createMockStore = configureMockStore([thunk]);
const defaultState = [];
const store = createMockStore(defaultState);
/** reset mock */
afterEach(() => jest.resetAllMocks());

test("should register a  user ", async () => {
  axios.post.mockImplementation(() => {
    return Promise.resolve({
      status: 200,
      body: {
        token: "testToken",
      },
    });
  });
  const res = await axios.post("/api/users");
  console.log(res.body);
  const testUser = {
    name: "testName",
    email: "test@email.com",
    password: "testPassword",
  };
  await store.dispatch(register(testUser)).then(() => {
    expect(store.getActions()[0]).toEqual({
      type: REGISTER_SUCCESS,
      payload: {
        token: "testToken",
        isAuthenticated: true,
        loading: false,
      },
    });
  });
});

回答1:


You're quite close to get it done. The thing is you're mocking axios.post while your implementation is using directly from axios object. As long as you mock axios object then it would work as it should. Here is proposed changes, please check inline comments for things you should also change:

test("should register a user ", async () => {
  // Mock `axios` object directly
  axios.mockImplementation(() => {
    return Promise.resolve({
      status: 200,
      // should also change from `body` to `data` as well
      data: {
        token: "testToken",
      },
    });
  });
  
  // it will no longer work since the mock is changed
  // const res = await axios.post("/api/users");
  // console.log(res.body);

  const testUser = {
    name: "testName",
    email: "test@email.com",
    password: "testPassword",
  };
  await store.dispatch(register(testUser)).then(() => {
    expect(store.getActions()[0]).toEqual({
      type: REGISTER_SUCCESS,
      payload: {
        token: "testToken",
        isAuthenticated: true,
        loading: false,
      },
    });
  });
});


来源:https://stackoverflow.com/questions/65856663/how-to-jest-test-an-async-action-with-axios-in-react

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!