Test Effects Generated from React the useEffect Hook

Kent C. Dodds
InstructorKent C. Dodds
Share this video with your friends

Social Share Links

Send Tweet
Published 5 years ago
Updated 3 years ago

NOTE: React Suspense for data fetching is VERY ALPHA and this API is undocumented, unsupported, and will likely change.

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

Instructor: [0:00] We've got a counter component here that has some logic for getting the initial state as well as keeping that state updated in local storage. I want to write a test to make sure that all of these is working and will continue to work as I make changes to this component in the future.

[0:13] Let's go ahead. I'm going to make a new test that says reads and writes to local storage. In here, the first thing I want to do is I'll say window.localStorage.setItem of count to be three. The reason that I want to set it to be three initially is so that I can verify that when we say getItemCount, it's going to get the correct item.

[0:40] We'll do that. Then we'll go ahead and render the counter. We'll get our container from that. We'll get the button, container firstChild.

[0:51] Normally, I would be using some of the other queries that React Testing Library is going to exposed to me to get this button, maybe get by text. In our simple scenario, container firstChild is going to work fine.

[1:05] We're getting the button from the firstChild. Now, we're going to just do this exact same expectation. In fact, I'm going to just copy all of the stuff and we'll just put that right there.

[1:14] For us, because we're setting local storage to three, we're going to expect it to start out as three before we click it, and then after we click it, we'll expect it to be four. If I save that and open up my test, I'm going to see that it is working properly. That's just make sure that can't fail.

[1:32] Great, my assertion is running. That definitely can't fail. We're all set. Now, I'm going to make one other assertion now because I want to make sure that local storage has the right value in it as well.

[1:42] We're going to say getItemCount. We want to assert that as four. I'm going to say expect that to be four. Sweet, my test is still passing.

[1:56] Now one last thing that I want to do is I want to make sure that our tests are working in isolation from one another. I'm going to come down here and we're going to say removeItemCount so that we clean up after ourselves.

[2:08] If we add some more tests in here, they're not going to bump into one another. For example, if I added another test, and in this case, I didn't have removeItem and I didn't have setItem. I would expect this to initialize the zero. That test is actually going to fail because it still has that value of four for when I clicked on the button after having set it to three.

[2:31] I want to make sure that I'm cleaning up after myself. Now, I won't want to do this every single time and every single test. What I'm going to do is I'll add in after each. After each of my test, I'm going to remove that countItem or the item from local storage called count. I don't have to do this in every single test and my tests are still going to pass that way.

[2:53] I'll just go ahead and get rid of that temporary test there. We're all set.

[2:58] In review, what we had to do here was I initialized the global state that my component relies upon by setting local storage to have an item of count as three, then I rendered my thing. I got the button out. I expected the initial state to reflect what was in local storage.

[3:18] I fire a quick event on that button. I verify that local storage has the new updated value and the button content has the correct value as well.

[3:30] Now if I were to make some sort of change in here like maybe I had a typo in there or something, my dependencies were incorrect, then I would get a failing test, which is exactly what I'm looking for. We'll just restore that to its former glory and we're good to go with our test.

~ 5 years ago

awesome tests!

Shawn Mitchell
Shawn Mitchell
~ 5 years ago

Looks like you added 3 expects but your test output only show 2 test passing?

House Developer
House Developer
~ 5 years ago

Hi Kent. Great videos, thanks! When I watched this the first time it was part of a playlist covering a lot of nice things regarding hooks and suspense, but now I can't find the playlist anymore… What happened?

Kent C. Dodds
Kent C. Doddsinstructor
~ 5 years ago

Tomeu, thanks!

Shawn, the output only shows one test for each call of test. You can have multiple expects in a single test.

House, thanks! You can find the full playlist here: http://kcd.im/hooks-and-suspense

Egghead's working on making playlists surface better in the UI.

Markdown supported.
Become a member to join the discussionEnroll Today