0
votes

I'm trying to test my async action creators in create-react-app but I don't have enough information to fix the issue. This is my first time to test async actions in React. I'm using Axios for fetching API and Jest mock to create a mock functions.

Here's fetch function:

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

Here's my test:

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: '[email protected]' });
        console.log(t);
      });
    });
  });
});

Here's the error that I'm getting but don't understand because I am mocking it as a Resolved value but it goes to my catch block in my actual API call.

enter image description here

1
How did u create axiosInstance?slideshowp2
yes I created it already. :(aRtoo

1 Answers

0
votes

Took me some time to get it but I finally figured it out.

So I have this folder structure:

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

then inside the __mock__ folder I have this. This will simulate my "POST" singup API

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

since I'm using axios instance like:

import axios from 'axios';

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

export default axiosInstance;

then consuming it in my API folder like:

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

then I have to setup my test like this:

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: '[email protected]' });
        console.log(t);
      });
    });
  });
});

jest.mock() will take path to your mocked folder. Then I can used my mockedAxios variable to get all properties in my __mock__/api.ts file and test my API by giving it a Promise. The return of the t variable will be whatever you put inside the Promise.resolve method.