How to Use Apollo to Test GraphQL Requests in React

In this lesson, we'll talk about one other minor testing utility we'll use to help mock GraphQL requests in our tests - Apollo React Testing.

Project Source Code

Get the project source code below, and follow along with the lesson material.

Download Project Source Code

To set up the project on your local machine, please follow the directions provided in the README.md file. If you run into any issues with running the project source code, then feel free to reach out to the author in the course's Discord channel.

This lesson preview is part of the TinyHouse: A Fullstack React Masterclass with TypeScript and GraphQL - Part Two course and can be unlocked immediately with a single-time purchase. Already have access to this course? Log in here.

This video is available to students only
Unlock This Course

Get unlimited access to TinyHouse: A Fullstack React Masterclass with TypeScript and GraphQL - Part Two with a single-time purchase.

Thumbnail for the \newline course TinyHouse: A Fullstack React Masterclass with TypeScript and GraphQL - Part Two
  • [00:00 - 00:18] In this lesson, we'll spend a few minutes talking about another tool we'll use in our testing suite, and that is the Apollo React Testing Library. If we recall in our client application, a large number of components in our app interact with our GraphQL API to query or mutate a data.

    [00:19 - 00:29] For example, something like this might seem pretty familiar at this moment. In a lot of the parent components like Home or Listings or User, we would employ the use query hook.

    [00:30 - 00:56] We would specify the query you want to make, and from this we would get information of this query, such as its loading status, such as the data when available, and any or all potential errors. Depending on the status of the query, in other words depending on whether the query is loading, whether an error has occurred or whether data is available, we would then conditionally render different UI if we were to render a component like this in our test.

    [00:57 - 01:12] Our test would most likely fail just from the get-go. And the reason being is when we actually specify our queries like this in the component, these queries actually make a network request to the server to get the information that's necessary.

    [01:13 - 01:26] In our test, our test would be unaware of the status of the query unless it actually makes a network request. We would once want our test to make a network request to the server to determine the status or the efficiency of our components in our client.

    [01:27 - 01:36] Remember, we're testing everything as a unit. As we write unit tests for this component, the only things we care is that this component behaves the way we expect it to.

    [01:37 - 01:54] When data is there, when it's loading or when it's error, we don't actually want to have our component or our test for our components be responsible in making these requests. So with that being said, how do we actually manipulate the behavior of this query in the different conditions that we want to test for?

    [01:55 - 02:11] This is where we can now use a "Nother Library" known as Apollo React Testing, which allows us to mock the GraphQL requests in our tests. The Apollo React Testing Library allows us to import a component known as "M ocked Provider".

    [02:12 - 02:37] "Mocked Provider" helps create a "Mocked Version of Apollo Provider". If we recall, a "Polar Provider" was the root-level component we used in our source index file of our React application, where we were able to instantiate Apollo or the React Apollo library everywhere in our React app. Why is this helpful? Because now in our tests, we will be able to specify the exact response of our GraphQL requests in our tests.

    [02:38 - 02:58] Whether the request would fail, whether it would be in its loading status, whether it's successful and data is available, we can declare all these different situations, and then we can test our component behaves under these different situations. And, more importantly or pretty important, is it does not make network requests . It's simply a "Mocking Library".

    [02:59 - 03:27] It allows us to mock our requests. Like I mentioned previously, we don't want to make network requests in our tests. Okay, how does this "Mocked Provider" work? In our tests, all we need to do is essentially use the "Mocked Provider" component as the parent, and specify the child component we want to render. This "Mocked Provider" component expects a "Mocks" prop, where we specify an array of the information that we want our GraphQL request to be.

    [03:28 - 03:48] If we specify an empty array as the value, this essentially mimics the loading status of our requests. So if we were to do something like this, we can simply get the query helpers we need from the React testing library, and then we can assert that our component behaves the way we expect it to when the request is loading.

    [03:49 - 04:10] If we wanted to mock the error status of our request, all we need to do is prepare our actual request information with a request property that resembles the request being made in the component. Like this is a query being made, these are the variables we pass in, and instead of saying the data that's going to be returned, we can just specify an error.

    [04:11 - 04:28] And by passing this particular mock object as part of the array in the "Mocks" prop, we can now mock the behavior of the component when a request is to error out. And there's also the two different or a few different error states we can do. We can do the "Net's work error" behavior, we can specify a GraphQL error.

    [04:29 - 04:45] Another potential error, I guess, is to not necessarily have the error property, but then specify the data property with no data. So all of these different behaviors can sort of be tested by just mocking the expected error status that we want.

    [04:46 - 05:08] And lastly, if we want to test the components when data is finally available, we just need to specify our mock, as we mentioned, with the request information that's being made, what is the query, what are the variables we're doing, or using in this particular query, and then we can specify the results or the data that we'll get from a successful request. So with the listings query we made before in our app, the response looks something like this.

    [05:09 - 05:22] It would have a region, the total number of listings that exist in that region, and a result property that has all the different listings in it. And that's pretty much it. This is literally how we'll use the Apollo testing utility.

    [05:23 - 05:38] We just need to specify the expected response we'll want to test for, and then we'll just test the component in that condition that we specified. Now one other thing to quickly mention is that GraphQL requests, or just API requests in general, are asynchronous.

    [05:39 - 06:04] When we make the request, there's a period of time where the request is actually being made, and then finally, if successful, or if it does error potentially, is when the actual request ends. So if we were to test the successful status of data being available, if we think about it, in our component, we actually specify that only when data is available, do we actually show the expected UI?

    [06:05 - 06:17] But when we do that, we're sort of specifying that when data is finally or finally arrives from our API, do we do what we need to do? And our query is set up in such a way that it's an asynchronous behavior.

    [06:18 - 06:28] So to sort of mimic this asynchronous behavior, the React testing library actually provides a few different utilities for us to use. And the more simple and direct one is the wait for utility.

    [06:29 - 06:49] Now, this wait for utility is helpful because it allows us to essentially wait for elements to appear or disappear in response to an action. But in particularly for our case, it's helpful because it allows us to mock our API calls, and then we can wait for our mock promises to then resolve.

    [06:50 - 07:03] So in this instance, here's an expected test case that we can essentially write . We can specify a test that says we expect the UI to be what we want it to be when data is available from our request.

    [07:04 - 07:13] We can specify the mock GraphQL response that we want. We can then render our component, use the mock provider component from Apollo testing.

    [07:14 - 07:20] We can then specify this mock response in the mock's prop that it takes. We then render the listings components within.

    [07:21 - 07:32] We destruct or obtain the query utility that we want. And then we say we wait for the promise to eventually resolve for us to then validate or make our assertion.

    [07:33 - 07:43] So then we can say we expect this particular node, whatever we attempt to query , to not be null or to exist or to equal something. Quick notes before we close this lesson.

    [07:44 - 07:59] All the tooling and utilities and libraries we're using aren't the only libraries we need to use. There's technically many or dozens of different libraries that provide these different utilities or helpers in different ways.

    [08:00 - 08:13] What I'm trying to convey here are these are the libraries we'll use, but the main takeaway is the thought process that's actually being conducted to write these tests. If you were to see this from the very beginning, you might be wondering what is actually happening here.

    [08:14 - 08:21] But at this moment, I hope it's pretty apparent that what this trust is trying to convey. It's the fact that we're trying to make an API or mock API request.

    [08:22 - 08:32] We're then getting the utilities necessary to find the nodes we're looking for, and then we're waiting asynchronously for that request to finish before making our assertions.