This post is part of my series on unit testing with Jest in React Native. You can find the introduction here.
By now you should have a solid understanding of how testing works in React Native. But there is one important concept left to go over, that is integrating redux into your tests. Redux is the industry standard for global state management in React applications. Even though React Context is supposed to replace Redux, it is not there yet. So how do we test Redux-connected components with Jest and react-native-testing-library?
Sample component
To test our implementation, we will use this component:
This component grabs the count parameter from the state to display it and dispatches an INCREMENT
action whenever you press the button. Simple enough.
Inline integration
If you do not have to do this often, you may use inline redux integration. To do this, you will need to install redux-mock-store
library. This library provides a great interface to assert dispatched actions on your redux store and test your components. With it, you can write code like this in your tests:
In the describe
section, we create a mockStore
function. It will be used as a factory for mock stores. It can be extended with middlewares (thunk, for instance), but I will leave it as an exercise for the reader. Then, in the first test, we create a store
with {count: 5}
as the initial state. Next, we render the Counter
(wrapped in Provider
) to assert that it indeed renders 5.
The second test is a bit more confusing. We create the store the same way, but then we send a press event to the button. The button should dispatch an action on the store, which we assert later.
Overriding the render function
While the inline approach works perfectly well, this is not scalable and will result in a lot of repetition in a large codebase. To mitigate this, consider overriding the render function so it injects a Provider
with a store for you. To achieve this, create a test-utils.js
file and put this code in it:
We create the mock store the same way we created it in earlier tests. The difference is that now the same store will be used for all the tests, so consider filling in the real INITIAL_STATE
from your root reducer. Then we define the reduxRender
funciton, which will wrap everything in a Provider
. Lastly, re-export everything from react-native-testing-library for convenience. Now look at the same tests from earlier, but using this new method:
Now, code became shorter and more readable without compromising the functionality, a win-win situation. Note the store.clearActions()
on line 7: since we are using the same-store across tests, it is important to reset it after every test.
This is the last post in my series on React Native unit testing. I hope now you have an understanding why tests are important and how to write them for different purposes.
Thanks lot!
I’d been searching for about a week trying to find a decent tutorial on React-Native testing – these are by far the best – easy to understand, well explained, and very on point.
Thanks very much!!
Hello Michael Krasnov,
i read your code i want say thanks. i want to ask some thing i got a issue below i mention
“Could not find “store” in the context of “Connect(MyEquipment)”. Either wrap the root component in a , or pass a custom React context provider to and the corresponding React context consumer to Connect(MyEquipment) in connect options.”
This issue occurs when i write jest test case simple render the class or nothing .
A am also share my class
function MyEquipment(props) {
code here…
………
}
export default connect(mapStateToProps, {
getMyEquipmentSummary,
setCurrentEquipmentSerialNumber,
setCurrentOrderNumber,
getDeliveryOrders,
loadCompleted,
})(MyEquipment);
Can you help me i am already spent a week on this point.
Thank you