Bikram
Bikram

Reputation: 343

How can I test custom callbacks passed to Axios API using jest + enzyme

In my react application I have an async api call done with axios. And that api call does accept a custom callback.

I am able to test the axios api call using Jest + Enzyme. But not able to test the custom callback method.

Note: I have mocked my axios module.

src/mocks/axios.js

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

auth.api.js

import Axios from 'axios';
import { AUTH_SERVER_URL } from './../../settings';
import { setAuthToken } from '../actions/auth/auth.action';

export const saveUsers = (user, dispatch) => {
    const URL = `${AUTH_SERVER_URL}/auth/register`;
    Axios.post(URL, user)
        .then(response => {
            const { data } = response;
            const token = {
                accessToken: data.access_token,
            };
            return token;
        })
        .then(token => dispatch(setAuthToken(token)))
        .catch(error => {
            if (error.response) {
                console.error(error.response.data.message);
            }
        })
}

And here is my test code.

spec.js

import mockAxios from 'axios';
import { AUTH_SERVER_URL } from './../../settings';
import { saveUsers } from './auth.api';
import { setAuthToken } from '../actions/auth/auth.action';

describe('Authentication API', () => {
    it('saveUsers', () => {

        const user = { x: 'test' }
        const dispatch = jest.fn(); // need to test this dispatch function gets called or not
        const response = {
            data: {
                access_token: 'access_token',
            }
        };
        const expectedToken = {
            accessToken: 'access_token',
        };
        mockAxios.post.mockImplementationOnce(() => Promise.resolve(response));

        saveUsers(user, dispatch);

        const url = `${AUTH_SERVER_URL}/auth/register`;
        expect(mockAxios.post).toHaveBeenCalledTimes(1);
        expect(mockAxios.post).toHaveBeenCalledWith(url, user);
        console.log(dispatch.mock.calls);

        expect(dispatch).toHaveBeenCalledTimes(1); // failed
        expect(dispatch).toHaveBeenCalledWith(setAuthToken(expectedToken)); // failed

    });
})

Please help me in this

Upvotes: 1

Views: 1066

Answers (2)

Bikram
Bikram

Reputation: 343

Thanks to @Jakub Janik for his answer.

Bellow is my answer without using flush-promise package. But it is using the concept behind flush-promise.

import mockAxios from 'axios';
import { AUTH_SERVER_URL } from './../../settings';
import { saveUsers } from './auth.api';
import { setAuthToken } from '../actions/auth/auth.action';

// A helper function can turn that into a promise itself so you don't need to deal with the done callback.
const flushPromises = () => new Promise(resolve => setImmediate(resolve));

describe('Authentication API', () => {
    it('saveUsers', async () => {

        const user = { x: 'test' }
        const dispatch = jest.fn(); // need to test this dispatch function gets called or not
        const response = {
            data: {
                access_token: 'access_token',
            }
        };
        const expectedToken = {
            accessToken: 'access_token',
        };
        mockAxios.post.mockImplementationOnce(() => Promise.resolve(response));

        saveUsers(user, dispatch);

        const url = `${AUTH_SERVER_URL}/auth/register`;
        expect(mockAxios.post).toHaveBeenCalledTimes(1);
        expect(mockAxios.post).toHaveBeenCalledWith(url, user);

        await flushPromises(); // Magic happens here

        expect(dispatch).toHaveBeenCalledTimes(1);
        expect(dispatch).toHaveBeenCalledWith(setAuthToken(expectedToken));

    });
})

Upvotes: 1

Kuba Janik
Kuba Janik

Reputation: 333

Try to install this package flush-promises.

Then import it in your test file

import flushPromises from 'flush-promises';

And add it before your assertions.

...

await flushPromises();

expect(dispatch).toHaveBeenCalledTimes(1);
expect(dispatch).toHaveBeenCalledWith(setAuthToken(expectedToken)); 

And here add async.

it('saveUsers', async () => {

But I'm not sure if it will help.

Upvotes: 2

Related Questions