Axios library is used to fetch the data. Usually in react components, we use the Axios library to do the data fetching part. Unit testing the data fetch part is very important so that both the success and the error condition are handled and tested.
Here is a sample React component that uses the Axios library in the lifecycle. We are going to fetch the response, get the name
from the response, and set the state variable in the success condition.
import React, { Component } from 'react'; import axios from 'axios'; class MockComponent extends Component{ state = { name: '', error: false } componentDidMount(){ axios({ url: '/', method: 'POST' }).then((data)=>{ console.log('data',data) const { name } = data; this.setState({ name }) }).catch(()=>{ this.setState({ error: true }) }) } render(){ const { name, error } = this.state; if(error){ return ( <div> Error fetching data </div> ) } return ( <div> This is a mock component {name} </div> ) } } export default MockComponent;
In case of error, we are going to set the error state as true, which will render the generic error text.
Now we are going to use the react testing library to test the above component. If you do not have the testing library installed, then install the dev dependency by running the command below.
npm install --save-dev @testing-library/react
Now we have the react testing library installed. Let us start writing the unit test case for the above component.
We have to mock the axios library so that we can control the success and error condition and it can be easily reproduced in the test case. The axios library is a es6 module, so we are going to mock it as follows.
jest.mock('axios', () => { return { __esModule: true, default: jest.fn() } });
In the above code, we have mocked the axios library using jest.mock
. jest.mock
accepts a callback function, where we can define the properties of the axios library. Because it is an es6 module, we have returned __esModule
as true
. We have to also implement the default
export of the axios library as we are using the default
import in our MockComponent
.
We have assigned a mock function to the default
export of Axios, because we are going to spy on it and return the resolved value or rejected value in the test case as follows
const axios = require('axios'); jest.spyOn(axios, 'default').mockResolvedValue({ name: 'abc' })
const axios = require('axios'); jest.spyOn(axios, 'default').mockRejectedValue()
We have now understood how to mock the Axios library and control it by spying on the Axios library and returning the resolved or rejected value as per our test case. So let us write the unit test case for success condition.
import React from 'react'; import { render } from 'react-testing-library'; jest.mock('axios', () => { return { __esModule: true, default: jest.fn() } }); import MockComponent from '../Mocks'; describe('Mocks', () => { it('should render the name', (done) => { const axios = require('axios'); jest.spyOn(axios, 'default').mockResolvedValue({ name: 'abc' }) const wrapper = render(One point to note in the above unit test case is that we have inserted the mock before importing the MockComponent
.
First, we mock the Axios component in the imports section. Then in the test case, we require the mock Axios library to get the instance, so that we can add a spy on it and mock its implementation as well.
We are going to use the react testing library to render the component.
const wrapper = render(<MockComponent>);
The axios call is going to be made in the componentDidMount
lifecycle. So we are going to verify if the text of success condition has been rendered in the DOM.
We have to use process.nextTick
because the setState
is an async process.
Also note that we have used the done
callback, so that the test case will wait unit the done callback is called. We call the done
callback inside the process.nextTick
function.
As discussed above, we will follow the similar pattern and write the unit test case for the error condition. But in the mock implementation, we have to send the rejected
value, and not the resolved
value so that the catch block of the axios call is used.