'Mocking axios.post response triggered by button in react component
I would like to test (with RTL and jest) the api.post (with axios) triggered by a button in my react component bellow. It's about a login display with 2 inputs fields (email and password) and 2 buttons (enter and register). Both the enter and the register buttons called asynchronous functions.
// src > pages > Login
import React, { useState } from 'react';
import { useDispatch } from 'react-redux';
import { useNavigate } from 'react-router-dom';
import { saveToken } from '../app/slices/tokenSlice';
import { saveUserData } from '../app/slices/userSlice';
import api from '../services/api';
function Login() {
const [loginState, setLoginState] = useState({
email: '',
password: '',
});
const navigate = useNavigate();
const dispatch = useDispatch();
const handleChange = ({ target: { name, value } }) => {
setLoginState({
...loginState,
[name]: value,
});
};
const enterUser = async () => {
await api.post('/login', { ...loginState })
.then((response) => {
dispatch(saveToken(response.data.token));
dispatch(saveUserData(loginState));
navigate('/home');
})
.catch((error) => {
alert(error.message);
});
};
const registerUser = async () => {
api.post('/user', loginState)
.then(() => {
alert('Usuário cadastrado com sucesso!');
})
.catch((error) => {
alert(error.message);
});
};
return (
<div>
<label htmlFor="email">
Email:
<input
id="email"
name="email"
onChange={handleChange}
placeholder="Email"
type="text"
value={loginState.email}
/>
</label>
<label htmlFor="password">
Senha:
<input
id="password"
name="password"
onChange={handleChange}
type="password"
value={loginState.password}
/>
</label>
<button
name="btnEnterUser"
type="button"
onClick={() => enterUser()}
>
Entrar
</button>
<button
name="btnRegisterUser"
type="button"
onClick={() => registerUser()}
>
Cadastrar
</button>
</div>
);
}
export default Login;
// src > services > api.js
import axios from 'axios';
const { BASE_URL } = process.env;
const api = axios.create({
baseURL: BASE_URL,
});
api.defaults.headers.post['Content-Type'] = 'application/json;charset=utf-8';
api.defaults.headers.post['Access-Control-Allow-Origin'] = '*';
export default api;
How can i develop a test with mock data related to "registerUser" and "enterUser" functions. I have tried many options with jest.fn(), jest.spyOn() and userEvent.click(btnRegister), where btnRegister is the element which i getByRole as you can check in my test file bellow:
// src > tests > login.test.js
import React from 'react';
import '@testing-library/jest-dom';
import { screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import Login from '../pages/Login';
import renderWithRouter from './renderWithRouter';
import api from '../services/api';
describe('Componente Login', () => {
let inputEmail;
let inputPassword;
let btnRegister;
let btnEnter;
const userEmail = '[email protected]';
const userPassword = '123456';
const tokenMock = {
token: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJfaWQiOiI2MjA4MWYyYzBhMWFhNzFmYjhjZjU2NjAiLCJlbWFpbCI6Im1hcmlhbmFAZ21haWwuY29tIiwiaWF0IjoxNjQ1MzIyMjU1LCJleHAiOjE2NDUzNDAyNTV9.TIgJFIzg1W0bisvJ3CfRsVCZr3kbKn13_NBN-Ah1U1w',
};
const userRegisteredResponseMock = {
user:
{
email: '[email protected]',
id: '6211a1d3eb25fc2418dec05a',
},
};
beforeAll(() => {
renderWithRouter(<Login />);
inputEmail = screen.getByLabelText(/email/i);
inputPassword = screen.getByLabelText(/senha/i);
btnRegister = screen.getByRole('button', { name: /cadastrar/i });
btnEnter = screen.getByRole('button', { name: /entrar/i });
userEvent.type(inputEmail, userEmail);
userEvent.type(inputPassword, userPassword);
});
it('Registro de usuário com sucesso', async () => {
// ************** DOESNT WORK **********************
// api.post = jest.fn().mockImplementation(() => {
// Promise.resolve(userRegisteredResponseMock);
// });
// api.post = jest.fn(() => Promise.resolve(userRegisteredResponseMock));
// api.post = jest.fn().mockResolvedValue(userRegisteredResponseMock);
// jest.spyOn(Login, 'enterUser');
// ****************************************************
userEvent.click(btnRegister);
expect(<"REGISTER USER" FUNCTION>).toBeCalledTimes(1);
});
});
I also have tried created "mocks" folder as jest documentation has mentioned in this link: https://jestjs.io/docs/manual-mocks , but without success.
Solution 1:[1]
in order to force jest using the mocked module, the jest.mock() function should be called.
import api from '../services/api';
...
jest.mock('../services/api');
...
api.post.mockResolvedValue(userRegisteredResponseMock);
it's also possible to mock axios module itself. furthermore, there's a jest-mock-axios npm module designed to achieve the behaviour.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Yone |
