Reputation: 343
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
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
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