i getting error like this when I want to test my React application which uses Redux, I want to test the thunk function register AssertionError: expected "spy" to be called with arguments: [ [Function] ]
// action.js
function asyncRegisterUser({ name, email, password }) {
return async (dispatch) => {
dispatch(showLoading());
try {
await api.register({ name, email, password });
} catch (error) {
alert(error.message);
}
dispatch(hideLoading());
};
}
export {
asyncRegisterUser,
};
// action.test.js
import { hideLoading, showLoading } from 'react-redux-loading-bar';
import {
afterEach, beforeEach, describe, expect, it, vi,
} from 'vitest';
import api from '../../utils/api';
import { asyncRegisterUser } from './action';
const fakeRegisterResponse = {
id: 'john_doe',
name: 'John Doe',
email: '[email protected]',
avatar: 'https://generated-image-url.jpg',
};
const fakeRegisterInput = {
name: 'John Doe',
email: '[email protected]',
password: 'JohnDoe',
};
const fakeErrorResponse = new Error('Ups, something went wrong');
describe('asyncRegisterUser thunk', () => {
beforeEach(() => {
api._registerUser = api.register;
});
afterEach(() => {
api.register = api._registerUser;
delete api._registerUser;
});
it('should dispatch action correctly when register success', async () => {
api.register = () => Promise.resolve(fakeRegisterResponse);
const dispatch = vi.fn();
await asyncRegisterUser(fakeRegisterInput)(dispatch);
expect(dispatch).toHaveBeenCalledWith(showLoading());
expect(dispatch).toHaveBeenCalledWith(
asyncRegisterUser(fakeRegisterInput), //ERROR HERE
);
expect(dispatch).toHaveBeenCalledWith(hideLoading());
});
it('should dispatch action and call alert correctly when register failed', async () => {
api.register = () => Promise.reject(fakeErrorResponse);
const dispatch = vi.fn();
window.alert = vi.fn();
await asyncRegisterUser(fakeRegisterInput)(dispatch);
expect(dispatch).toHaveBeenCalledWith(showLoading());
expect(dispatch).toHaveBeenCalledWith(hideLoading());
expect(window.alert).toHaveBeenCalledWith(fakeErrorResponse.message);
});
});
i wanna make test using vitest on react redux thunk function when i call register function, should dispatch action correctly when register success
In your asyncRegisterUser
action creator the dispatch
function is only called twice, once with showLoading()
and a second time with hideLoading()
.
function asyncRegisterUser({ name, email, password }) {
return async (dispatch) => {
dispatch(showLoading()); // <-- dispatch call #1
try {
await api.register({ name, email, password });
} catch (error) {
alert(error.message);
}
dispatch(hideLoading()); // <-- dispatch call #2
};
}
It would probably be very bad for your asyncRegisterUser
action to trigger calling itself so probably want to assert that this does not happen.
it('should dispatch action correctly when register success', async () => {
api.register = () => Promise.resolve(fakeRegisterResponse);
const dispatch = vi.fn();
await asyncRegisterUser(fakeRegisterInput)(dispatch);
expect(dispatch).toHaveBeenCalledWith(showLoading()); // <-- dispatch #1
// assert asyncRegisterUser action isn't recursively called
expect(dispatch).not.toHaveBeenCalledWith(
asyncRegisterUser(fakeRegisterInput),
);
expect(dispatch).toHaveBeenCalledWith(hideLoading()); // <-- dispatch #2
});
Otherwise, remove the middle assertion since dispatch
obviously doesn't call asyncRegisterUser
.
it('should dispatch action correctly when register success', async () => {
api.register = () => Promise.resolve(fakeRegisterResponse);
const dispatch = vi.fn();
await asyncRegisterUser(fakeRegisterInput)(dispatch);
expect(dispatch).toHaveBeenCalledWith(showLoading()); // <-- dispatch #1
expect(dispatch).toHaveBeenCalledWith(hideLoading()); // <-- dispatch #2
});