Unit Testing in React

Afaq Ahmad
6 min readJan 10, 2023

--

React + Redux unit testing

Writing unit tests for React Redux components is an important part of the software development process as it helps to ensure that your components are working correctly and to catch any issues early on. In this article, I will go through some tips and techniques for writing unit tests for React Redux components using Jest and Enzyme.

Here are some key tips for writing unit tests for React Redux components:

  1. Test the component's behavior, not its implementation: You should focus on testing how the component behaves in different scenarios, rather than testing its internal implementation details. This will make your tests less brittle and less likely to break when you make changes to your code.
  2. Test the component's interactions with the store: You should test how the component interacts with the store, including how it dispatches actions and updates its state.
  3. Test the component's interactions with its props: You should test how the component reacts to different props and how it updates its state based on those props.

To test React Redux components, you will need to use a testing library, such as Jest and Enzyme. Jest is a testing framework that allows you to run tests and make assertions. Enzyme is a library that allows you to easily test React components.

Here's an example of a simple test for a React Redux component that uses Jest and Enzyme:

import { createStore } from 'redux';
import { Provider } from 'react-redux';
import { mount } from 'enzyme';
import myReducer from './reducer';
import MyComponent from './MyComponent';

describe('MyComponent', () => {
let store;
let wrapper;

beforeEach(() => {
store = createStore(myReducer);
wrapper = mount(
<Provider store={store}>
<MyComponent />
</Provider>
);
});

it('should render the component', () => {
expect(wrapper.find(MyComponent)).toHaveLength(1);
});
});

In this example, we are using Jest's "describe" and "it" functions to define a test suite and a test case for the "MyComponent" component. We are using Enzyme's "mount" function to render the component with a Redux store provided by the "Provider" component. We are then using Jest’s “expect” function to make an assertion about the rendered component.

Here’s an example of how you might test the interactions between a React Redux component and the store:

import { createStore } from 'redux';
import { Provider } from 'react-redux';
import { mount } from 'enzyme';
import myReducer from './reducer';
import MyComponent from './MyComponent';
describe('MyComponent', () => {
let store;
let wrapper;
beforeEach(() => {
store = createStore(myReducer);
wrapper = mount(
<Provider store={store}>
<MyComponent />
</Provider>
);
});
it('should dispatch an action when a button is clicked', () => {
wrapper.find('button').simulate('click');
expect(store.getActions()).toEqual([{ type: 'MY_ACTION' }]);
});
});

In this example, we are using Enzyme’s “find” and “simulate” functions to find a button element in the rendered component and simulate a click event on it. We are then using Jest’s “expect” function to make an assertion about the actions that were dispatched to the store.

Here’s an example of how you might test the interactions between a React Redux component and its props:

import { createStore } from 'redux';
import { Provider } from 'react-redux';
import { mount } from 'enzyme';
import myReducer from './reducer';
import MyComponent from './MyComponent';
describe('MyComponent', () => {
let store;
let wrapper;
beforeEach(() => {
store = createStore(myReducer);
wrapper = mount(
<Provider store={store}>
<MyComponent myProp="test" />
</Provider>
);
});
it('should update its state based on the myProp prop', () => { expect(wrapper.find(MyComponent).prop('myProp')).toEqual('test'); expect(wrapper.find(MyComponent).state('myState')).toEqual('test');
});
});

In this example, we are using Enzyme's "find" and "prop" functions to find the "MyComponent" element in the rendered component and get its "myProp" prop. We are then using Jest's "expect" function to make an assertion about the value of the prop and the corresponding state of the component.

By following these tips and using the techniques demonstrated in these examples, you can effectively write unit tests for your React Redux components to ensure that they are working correctly and to catch any issues early on. It is important to remember to regularly update and maintain your unit tests as you make changes to your code to ensure that they are still relevant and accurate. It is also a good idea to write tests for edge cases and error scenarios to ensure that your components are handling them correctly. Here’s an example of how you might test an error scenario in a React Redux component:

import { createStore } from 'redux';
import { Provider } from 'react-redux';
import { mount } from 'enzyme';
import myReducer from './reducer';
import MyComponent from './MyComponent';
describe('MyComponent', () => {
let store;
let wrapper;
beforeEach(() => {
store = createStore(myReducer);
wrapper = mount(
<Provider store={store}>
<MyComponent />
</Provider>
);
});
it('should handle an error when an API call fails', () => {
const error = new Error('API call failed');
wrapper.find(MyComponent).instance().onError(error);
expect(wrapper.find(MyComponent).state('error')).toEqual(error);
});
});

In this example, we are using Enzyme’s “find” and “instance” functions to find the “MyComponent” element in the rendered component and get its instance. We are then simulating an error scenario by calling the “onError” method of the instance and passing in an error object. We are then using Jest’s “expect” function to make an assertion about the state of the component after the error has been handled.

It is also a good idea to test the component’s behavior when it receives different props. Here’s an example of how you might test the behavior of a React Redux component with different props:

import { createStore } from 'redux';
import { Provider } from 'react-redux';
import { mount } from 'enzyme';
import myReducer from './reducer';
import MyComponent from './MyComponent';
describe('MyComponent', () => {
let store;
let wrapper;
beforeEach(() => {
store = createStore(myReducer);
});
it('should render differently with different props', () => {
wrapper = mount(
<Provider store={store}>
<MyComponent myProp="test" />
</Provider>
);
expect(wrapper.find(MyComponent).html()).toEqual('<div>test</div>');
wrapper = mount(
<Provider store={store}>
<MyComponent myProp="different" />
</Provider>
);
expect(wrapper.find(MyComponent).html()).toEqual('<div>different</div>');
});
});

In this example, we are using Enzyme’s “find” and “html” functions to find the “MyComponent” element in the rendered component and get its HTML. We are then using Jest’s “expect” function to make an assertion about the HTML of the component based on the value of its “myProp” prop.

By testing the different scenarios and edge cases of your React Redux components, you can ensure that they are working correctly and handling errors and different prop values correctly. This will help to improve the reliability and maintainability of your code.

It is also a good idea to write tests for the component’s interactions with its children components. Here’s an example of how you might test the interactions between a React Redux component and its children components:

import { createStore } from 'redux';
import { Provider } from 'react-redux';
import { mount } from 'enzyme';
import myReducer from './reducer';
import MyComponent from './MyComponent';
import MyChildComponent from './MyChildComponent';
describe('MyComponent', () => {
let store;
let wrapper;
beforeEach(() => {
store = createStore(myReducer);
wrapper = mount(
<Provider store={store}>
<MyComponent>
<MyChildComponent />
</MyComponent>
</Provider>
);
});
it('should pass props to its children components', () => {
expect(wrapper.find(MyChildComponent).prop('myProp')).toEqual('test');
});
});

In this example, we are using Enzyme’s “find” and “prop” functions to find the “MyChildComponent” element in the rendered component and get its “myProp” prop. We are then using Jest’s “expect” function to make an assertion about the value of the prop.

By testing the interactions between a parent component and its children components, you can ensure that the parent component is correctly passing props and handling events from its children. This is especially important if the parent component is responsible for managing state or handling actions that affect the children components.

In summary, writing unit tests for your React Redux components is an important part of the software development process. By following best practices and testing the component’s behavior, interactions with the store and props, and interactions with its children components, you can ensure that your components are working correctly and improve the reliability and maintainability of your code.

--

--