The course is part of this learning path
This module looks at testing in React. You’ll learn how to set up a test environment, Jest, and other useful tools to test your React App.
The objectives of this module are to provide you with an understanding of:
- How to set up the test environment
- Snapshot testing
- How to test with Props
- How to mock components for testing
- Mock functions
- How to test components asynchronously
- How to test components with routing
- How to test custom hooks
This learning path is aimed at all who wish to learn how to use the ReactJS framework.
We welcome all feedback and suggestions - please contact us at email@example.com to let us know what you think.
We saw, when we were learning about forms, that sometimes state is not held on the form itself, but in the parent. To do this, we used inverse data flow to call functions in the parent by passing them through as props. If we're trying to unit test components, this makes a dependency on the parent, which is not good. Jest provides a way to mock functions in components, and we can leverage this in this situation. This is definite to jest.mock, that would be used if it was a utility function imported from another file.
To declare a mock function, we simply declare the mock function's name and set its value to jest.fn . If you need to, you can pass in an implementation callback. This is useful if the function being mocked is supposed to return something. We can then use this when we create the component in the test, passing the mock function name in as a prop. We're not concerned with the implementation of the function being mocked, because it's not declared in this component. We're happy if our component in the test calls this function with the correct arguments. Jest provides matches for function calls.
The main ones to know about are toHaveBeenCalled , which returns true if the mock function was called, and toHaveBeenCalledWith , which takes a set of arguments and returns true if the function has been called with the prescribed arguments. If you're unit testing functions, the other matches might be useful.
Let's see how we can implement this in a component test. We've modified the form so it has a submit button, and an onSubmit event handler. The form function will call submit from props, with the value of state. In the test, we will mock the submit function passed in by props, and use this when we render the form components. We'll simulate a click on the submit button. This should trigger the onSubmit event handler, which in turn, will trigger the submit function.
There's a small hiccup here. React Test Renderer doesn't allow us to fire events without the event handler being defined. So, we'll need to use a different library. We said earlier that we'd leverage some of the power of React Testing Library, so here goes. React Testing Library is baked into our project, so we don't need to install it as a dependency. In our test for the form, we declare mockSubmit as a Jest function. We've also set a const for the testName. We've changed the test for the onChange to work as a test and React Testing Library.
This involves creating a container using the render function. That's similar to using the create function to make a test instance in React Test Renderer. We then find the input in the container using the query selector function, and its CSS selector. And check its file using an empty string. React Testing Library has an enhanced user events, so we've leveraged this here to type in the input. It simulates typing testName into the input, firing it's onChange event and updating the state. We then assert that the value in the name input is the value that was typed, and this is the same as the test that we did earlier. Back to the mocking of functions now.
We can assume onSubmit event is fired, calling the handleSubmit function, and ultimately the submit function from props. And if we can record the calling of the submit function from props and what it was called with, we can make assertions. Setting a value in the name input then firing a click event on the submit button should do this, so that's how we test. In the second spec, we get the container, the name input, and the submit button.
We perform the actions of typing in the name input, and clicking on the button. We use fireEvent from React Testing Library here, instructing it to click on the identified button. We then assert that the mockSubmit function has been called exactly once. Checking this is good practice because it shows your functions work correctly. We also check that it has been called with the correct argument. That'll be an object with a key of name and a value of testName. Running these tests, showing that they pass.
You can use this function mocking any way that you have a dependency on a function that comes through props. So with this, you should be able to test the components that have their own internal data, or anything that's passed to them by props.
Introduction to Testing React with Jest - How to set up the Test Environment - Jest - The What and How of Testing in React - Snapshot Testing - Testing Components with Props - Mocking Components for Testing - Testing State Events Interactions - Testing Components Asynchronously - Testing Components with Routing - Testing Custom Hooks