Autoplay

    Test Effects Generated from React the useEffect Hook

    Kent C. DoddsKent C. Dodds

    React 16.7.0-alpha.0 was recently released and with it comes a set of experimental hooks and features. Use these with caution as they are likely to change in the near future.

    Our Counter component has grown in complexity and we need to figure out how to get it tested. In this lesson, we'll learn how to test the effects that are generated with useEffect.

    We'll cover:

    • How React schedules callbacks after the component renders
    • Keeping our tests isolated with afterEach
    • The rerender utility from React Testing Library's render
    reactReact
    Code

    Code

    Become a Member to view code

    You must be a Member to view code

    Access all courses and lessons, track your progress, gain confidence and expertise.

    Become a Member
    and unlock code for this lesson
    Transcript

    Transcript

    Instructor: 00:00 Our Counter component has gotten a little bit more complicated. Let's see how we can get this tested. We need to make sure that we test the useEffect here. We want to make sure that we can initialize local storage to a certain amount and that our Counter will be initialized to that.

    00:13 Let's go ahead and improve our test so that it can cover these cases. The first thing that we're going to do is I'm going to add an afterEach that will go ahead and window.localStorage.removeItem count. That way, we can keep our tests in isolation from each other.

    00:31 Then I'm going to go ahead and add a test, reads and updates local storage. Then here I'll go ahead and start out with window.localStorage.setItem count. We'll set that to three. Then we'll go ahead and render the Counter. We'll get our container from that.

    00:52 Then we'll get our button = container.firstChild. Then we'll expect the button.textContent to be three because that's the value that we set into local storage. If I open up my test and then save this, that test should be passing. Sweet.

    01:09 Next, let's go ahead and we'll fireEvent.click on the button. We can expect the textContent to be four now. We'll save that. Great. Now let's go ahead and we'll expect window.localStorage.getItem count to be four. That assertion is actually failing.

    01:30 The reason this is happening is because this useEffect callback is being called sometime after the render. React intentionally doesn't want this callback to block rendering. It schedules it to be done at a later time.

    01:43 We can force this callback to be run synchronously if we rerender this Counter component. That's what I'm going to do. We're going to pull in rerender from our render utilities. We'll say, "rerender Counter." We'll put that before we do this assertion. We get our test passing.

    02:00 In review, to make this work, we first added this afterEach so that we remove the count from local storage, so that our tests can be isolated from each other. Then we added this test, where we first set the local storage count item to three.

    02:13 Then we render our component. Then we verify that it is initialized to three, verifying that this behavior is working. Then we went ahead and clicked on the button. We verified that the button is behaving properly.

    02:24 We forced our effects to run by rerendering the component. Then we asserted that the local storage item of count was updated to four, verifying that this behavior is working appropriately.

    Discuss

    Discuss