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.
Should we test if props are rendered? Yes, we should. Apart from any default props that are supplied, default props have a part of the core React code and that's so their rendering functions is already tested. Doing it to test if prop types work? No. This is the concern of the prop types package and tests already exist for this. What we should do is see if the value of props received is rendered. Especially if it can change at one time because the component receives a new value for its props.
To test a component that has props we're gonna use the test render object again and find elements in the component that render based on the props. The roots of the test renderer can give us an object that allows us to find other elements within the component. We'll use helper methods of the test instance such as findAllByType and findAllByProps to help us locate all the test instances within the tree. The children object contains the contents for these instances and we will assert against them.
To show you some testing we're using that component that we made earlier in the course and you can see its code now. Note the class names we've given to the jsx expressions returned on line eight and 14. These will be used in the testing. In the test file we start by declaring a test suite. This component receives a lot of props which means lots of tests so we're grouping similar tests here. As we want to render the same component with the same props over and over again, we set some fixtures for the test. With a components test, this is defined so we can render it in the beforeEach function. We want to have a stable set of props that we can assert against so we define an object to use in both props and in our assertions. It has the keys and values that meet the components specified prop types.
Remember, we're not gonna test the prop types as this is not our direct concern in this component. The beforeEach function does two things here: It creates a testInstance using the create function on the component with props. Note how we pass in the props object using the spread operator. The second thing we create is a root testInstance object. This allows us to find other notes within this component. The first test suite you can see tests the h1Render. We find the first h1 in the tree using the findByType function. We pass in the element selector as a string. We then assert on this accessing the child array which in our case is a single text note that should contain the same string as supplied in the header prop key of the props object.
There's no need to test this component without the header text prop because this is concern of React core implementation and we assume that this renders if we don't supply anything. In the second spec in the file we have had to use a different find function. Unlike htmls query selector, which returns the first match, findByType expects to only find on of the specified type in the tree. If it finds more than one it returns an error. So we ought to to use the findAllByType function which returns an array of matches.
We knew that we were only concerned with the first element in this test so we've added the element index in the square brackets after the call to access the first paragraph. The assertion is, as for the previous test, checking that the child value is the same as the supplied prop. We mirror these tests for the next four specs for paragraphs with indexes one to four using slightly different matches and values. Note that we actually called function prop on line 64 to get its value. This is the last spec you can see on the screen. The next number displays render by an array. We may be satisfied if this is rendered as the improved child elements or we may wish to check the actual values. That is, I suppose, a decision for you.
We have opted to check each render of each of the paragraphs, failing if just one is wrong. We've also checked each of the renders from the object props display array. We access each array and check that the correct value for key has been used along with the correct value attached to that key. You'll notice in both cases we've used a className proper to the jsx expression generated in the component to find the element we wish to test. You can access any prop apart from key and rev in the findAllByProps and findByProps functions. Key and rev are reserved by React and for an error if you try and access them in tests.
There's no need to test a render of the unsupplied prop as this is a concern of React itself and it's supplied with a default anyway. Obviously if we're following tests during development we'd want tests to fail. We can supply failing values in the second half of our assertions before supplying the passing value if we're using this methodology.
So if we run the tests we have you can see that they all pass. The console gives us options for rerunning tests, a or enter to run all, f to run only failing tests and q to quit back to the terminal line. So now you've seen what you need to test and how to do it when you're thinking abour testing components that we save 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 - Mocking Functions - Testing Components Asynchronously - Testing Components with Routing - Testing Custom Hooks