Check out a free preview of the full Intermediate React, v5 course:
The "Testing Custom Hooks" Lesson is part of the full, Intermediate React, v5 course featured in this preview video. Here's what you'd learn in this lesson:

Brian tests the useBreedList custom hook. First, the hook is tested with an older sytax which involved providing a temporary React component to run the hook. The code is then refactored to use the renderHook() method which simplifies the test.

Get Unlimited Access Now

Transcript from the "Testing Custom Hooks" Lesson

>> Let's go test a custom hook. Part of the reasons writing custom hooks is great is because they become individually testable. Whereas if it's just like an effect in the middle of a component, it's really hard to test that. So we have useBreedList here, so the old way of writing these kind of tests with useBreedList and things like that, you actually have to like fake the component, right?

[00:00:26] And I can show you how to do that really quick if you want to. Let's just do it. Right, create a new file here, we're gonna call it useBreedList.test.jsx. This one actually has to be JSX because we're gonna write JSX in it. All right, so import ( expect, test ) from 'vitest'.

[00:00:52] import ( render ) from our testing library/react. import (queryClient, QueryClientProvider) from @tanstack/react-query. And import finally, usebreedList from '../usebreedList'. We're gonna have to make our default query client here really quick. const query client, this is just like a React router dom where React query requires to have a query client and a query client provider.

[00:01:38] So we have to kind of fake that for it. So queryClient is basically gonna be exactly what we do in our app.jsx = new QueryClient. defaultOptions, queries, staleTime, Infinity, cacheTime, Infinity, we are gonna add one more thing to it, which is retry: false. By default, React query will try three times and then give up, we don't want that in our test.

[00:02:15] If we're testing, if it fails, we want it to just fail, we don't want it to retry. Okay, function, we're gonna write this function called getBreedList. And it's gonna take an animal. We have this problem we're testing reacthooks.hooks, it only works inside of a React component so how can we test, we use breed list outside of a component?

[00:02:46] To answer your question, you can not, it only works inside of a React component, so we are going to make a React component. So we're gonna say let list, and then we're gonna read write function TestComponent and say list is assigned, useBreedList(animal) and then return null. It's kind of cheating, right?

[00:03:18] This is technically a valid React component, right? And then all we gotta have to do is render it. So we're gonna say render, queryClientProvider, client is assigned queryClient and then we're just going to render a test component. Right, this is gonna go through all the lifecycle, it's gonna call useBreedList, and then it's going to save the list here.

[00:03:49] So then all we have to do down here is return list. Kind of silly, right? It's a bit of like sacrificing the right goat. But now that we've done all this, we can write a little test down here. gives an empty list with no animal provided, async function.

[00:04:25] Okay, and then all we have to say is const breedList and status = getBreedList with nothing, right? And then we're gonna say expect(breedList).toHaveLength(0). expect(status).toBe of loading, I don't remember what the status is supposed to be, but loading sounds appropriate to me. Lo and behold, it works, right? If I say 1 here, it's gonna crash.

[00:05:07] If I say 0, it's gonna work. We had to write 37 lines of code to test, eighth.grade, it's a pretty simple hook. And once you write something like this, you can test any hook this way, right? And this is how we used to have to write things like this.

[00:05:39] Luckily, now with testing library, you can actually get something out of it. That allows you to test hooks directly without having to do all this faking stuff. So let's try giving that a shot. So we're going to expect in tests render, we got that, queryCient, queryClientProvider, we need all of this stuff.

[00:06:09] You do need the queryClient, you can delete all this get brainless stuff. Okay, and then instead of doing it, we'll just rewrite this test totally. Now we can say const (result) is assigned renderHook. We got renderHook from testing library, so instead of render, we want renderHook, this is relatively new, this is new since I last taught the course, I think.

[00:06:49] And you just give it a function of what you're trying to get out right, so this is all we're gonna need for that. And then we do have to give it a wrapper, right? So this is gonna be a function with children And this is where we can give it QueryClientProvider with a queryClient is assigned.

[00:07:28] queryClient. And you just give it children in the middle of that there. Okay, all of this rigmarole will end up with result and result will be whatever you expected back from the hook. So now I can say const (breedList, status) is assigned result.current. And I can say expect (breedList).toHaveLength0, toHaveLength0, and expect(status).toBeLoading.

[00:08:15] So all right, we fail, what happened here? No query client set, did I not set that? Did you install a dependency?
>> For the render hook?
>> Yeah.
>> No. So it's actually, it's built into testing library React now.
>> You didn't have to install testing library/reacthooks.
>> That is the old one, that one does not work with React 18.

[00:08:54] That is what version seven of this course used to teach. useBreedList, no query, client sets. So, that's the part that I don't know why it's not unhappy about, because it is, it there. queryClientProvider, queryClient, queryClient. It's not queryClient, sorry it's just client. Here we go, sorry. So I had here on line 19, I had queryClient like this, it's not queryClient, it is just client.

[00:09:31] And that's all I needed, good.