React testing simplified with humble components.

Kerry Convery
2 min readMar 16, 2021

--

React components can contain a mix of logic state and side effects. With the React hooks, it is now possible to turn once pure functional components into impure ones.

When it comes to unit testing we know that testing a pure function is easier than testing an impure one, the same applies to React components which after all, can be built from simple functions.

Consider the following component, BookList

It’s simple enough so let’s take a look at how we might test it.

BookList is an impure functional component because it fetches data from an external source. The tests are relatively clean and simple even though we’ve had to stub fetch (or use mock service worker) to fake the API call. Can we do better? Yes, we can, by using the humble object pattern.

The humble object pattern helps improve testability by separating logic from side effects. Side effects are moved into a simple, humble object which does nothing but invoke the side effect and the function containing the logic.

Let's see how we can create a humble component using the humble object pattern.

First, let us create a pure component called BookListView that contains our logic.

BookList has become a humble component containing only the API service call and some state.

And now the tests.

Notice that the tests are much simpler now. However, we haven’t tested the BookList. That is because we can cover this component with end-to-end UI tests to ensure that everything is hooked up correctly.

We have made testing the component’s logic easier however there is still a problem. What happens if we were to use the BookList component inside another pure component? The pure component will become impure and we are back to mocking and stubbing again. 🤔

To fix this we can use the component composition techniques described here.

And we can compose the impure BookList component with our pure one Pager without breaking its purity.

Again this can be testing using end-to-end testing to ensure that a list of books is rendered and that you can click on a page number to get the next page of books while allowing more fine-grained unit tests to be performed on the Pager component itself.

Conclusion

Pure components are easier to test than impure ones so we should strive to keep our components pure whenever possible. Here we have used the humble object pattern to create a humble component called BookList which is free from logic. We’ve also seen how pure components can consume impure ones while maintaining their purity. This reminds me of container and view components, only the difference is that container components often contained logic as well as side effects.

--

--

Kerry Convery

Full Stack engineer and mentor specialising in React and AWS