# How to do unit test for watchquery in react

**URL:** <https://community.apollographql.com/t/how-to-do-unit-test-for-watchquery-in-react/6154>\
**Category:** Client SDKs\
**Tags:** client, web\
**Created:** [April 15, 2023, 6:18pm UTC](https://community.apollographql.com/t/how-to-do-unit-test-for-watchquery-in-react/6154 "2023-04-15T18:18:33Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![Eric\_Zhang](https://sea1.discourse-cdn.com/flex019/user_avatar/community.apollographql.com/eric_zhang/32/4201_2.png) [@Eric\_Zhang](https://community.apollographql.com/u/Eric_Zhang)\
**Post date:** [April 15, 2023, 6:18pm UTC](https://community.apollographql.com/t/how-to-do-unit-test-for-watchquery-in-react/6154/1 "2023-04-15T18:18:33Z")

</div>

I have a difficult time to unit test watch query. I tried mockWatchQuery and subscribeAndCount, which causes test timeout. It seems the subscription never receive any data. Please, provide a guidance how to mock and test that. Thank you!

---

<div class="post-metadata">

**Author:** ![jerelmiller](https://sea1.discourse-cdn.com/flex019/user_avatar/community.apollographql.com/jerelmiller/32/3314_2.png) [@jerelmiller](https://community.apollographql.com/u/jerelmiller)\
**Post date:** [April 15, 2023, 11:14pm UTC](https://community.apollographql.com/t/how-to-do-unit-test-for-watchquery-in-react/6154/2 "2023-04-15T23:14:35Z")

</div>

Hey @Eric_Zhang 👋

Would you mind pasting a sample of a test that times out on you? I’d be happy to give some advice.

---

<div class="post-metadata">

**Author:** ![Eric\_Zhang](https://sea1.discourse-cdn.com/flex019/user_avatar/community.apollographql.com/eric_zhang/32/4201_2.png) [@Eric\_Zhang](https://community.apollographql.com/u/Eric_Zhang)\
**Post date:** [April 15, 2023, 11:39pm UTC](https://community.apollographql.com/t/how-to-do-unit-test-for-watchquery-in-react/6154/3 "2023-04-15T23:39:26Z")

</div>

Thanks Jerel,  
I have a custom hooks look like

```auto
const useCustomHook = () => {
  const {data: listItems} = useListItemsQuery(...);
  const [result, setResult] = useState(null);

  useEffect(() => {
      const subscriptions = new Set<ObservableSubscription>();
      const completedResult = [];
  
       if (listItems && listItems.length > 0) {
            listItems.forEach((item) => {
                const observable = client.watchQuery({
                   query: GetItemDocument
                });
                const subscription = observable.subscribe({
                     next: (res) => {
                        if(res.status === 'pending') {
                             observable.startPolling(POLL_INTERVAL);
                         } else {
                             observable.stopPolling();
                            completedResult = completedResult.concat(res);
                             subscription.unsubscribe();
                             subscriptions.delete(subscription);

                             if (subscriptions.size === 0) {
                                setResult(completedResult);
                             }
                         }
                     }
                });
                subscriptions.add(subscription);
            })
       }

      return () => {
        subscriptions.forEach((subscription) => subscription.unsubscribe());
        subscriptions.clear();
      };
   }, [listItems])

   return {result};
}

```

Here is my unit test which timed out.

```auto
import { itAsync, MockedResponse, subscribeAndCount } from '@apollo/client/testing';
import mockWatchQuery from '@apollo/client/testing/core/mocking/mockWatchQuery';

itAsync('should return list item if all items are complete.', (resolve, reject) => {
    getHookResult( // helper func for renderHook from '@testing-library/react'
      () =>
        useCustomHook(...),
      [listItemsSuccessMock],
    );

    const observable: ObservableQuery<any> = mockWatchQuery(
      {
        request: {
          query: GetItemDocument,
          variables: ...,
        },
        result: ..., // before polling
      },
      {
        request: {
          query: GetItemDocument,
          variables: ...,
        },
        result: ... // after polling
      },
    );

    subscribeAndCount(reject, observable, (handleCount, result) => {
      if (handleCount === 1) {
        expect(result.data).toEqual(beforePollingdata);
        expect(result.loading).toBe(false);
        observable.setOptions({ query: ListWorkflowRunsDocument, pollInterval: 0 });
      }

      if (handleCount === 2) {
        expect(result.loading).toBeTruthy();
      }

      if (handleCount === 3) {
        expect(result.loading).toBe(false);
        expect(result.data).toEqual(afterPollingdata);
        resolve();
      }
    });
  });

```

Is the subscribeAndCount only for testing observableQuery, but not how we test ObservableSubscription.

---

<div class="post-metadata">

**Author:** ![jerelmiller](https://sea1.discourse-cdn.com/flex019/user_avatar/community.apollographql.com/jerelmiller/32/3314_2.png) [@jerelmiller](https://community.apollographql.com/u/jerelmiller)\
**Post date:** [April 17, 2023, 12:02am UTC](https://community.apollographql.com/t/how-to-do-unit-test-for-watchquery-in-react/6154/4 "2023-04-17T00:02:41Z")

</div>

Hey @Eric_Zhang

Thanks for those code snippets! I’m curious, are you trying to test the observables inside your hook? It looks like you are testing against an created from your test (the one created via `mockWatchQuery`) that is completely disconnected from the observables created inside your hook, so even if you were able to get this specific test to work, I’d argue this could give you a false positive (by that I mean that if you can comment out your call to your hook and see your test still pass, that should give you some pause. Something I think your current implementation would do if it was currently working.)

Instead of trying to mock at the observable level, instead I recommend you try and mock at the network level. Any method in Apollo Client that would trigger a network will request go through your [link chain](https://www.apollographql.com/docs/react/api/link/introduction). In your development and production environments, your link chain typically uses an `HttpLink` to make network requests to your GraphQL server. In a testing environment however, you’ll generally want to use a `MockLink` to simulate the network requests in order to avoid actually hitting the network (this is what [`MockedProvider`](https://www.apollographql.com/docs/react/api/react/testing#mockedprovider) uses under the hood).

I’m not sure how you’re getting access to the `client` in your custom hook, but in order to properly mock the network requests, you’ll need to make sure that `client` uses `MockLink` instead of `HttpLink`. You can pass your mocks directly to that link and it will simulate each network request. This might look something like this:

```auto
import { MockLink } from '@apollo/client/testing';

const mocks = [
  {
    request: {
      query: GetItemDocument,
      variables: ...,
    },
    result: ..., // before polling
  },
  {
    request: {
      query: GetItemDocument,
      variables: ...,
    },
    result: ... // after polling
  },
];

const client = new ApolloClient({
  cache: new InMemoryCache(),

  // use `MockLink` in your test env instead `HttpLink` in your link chain
  link: new MockLink(mocks),
});

```

I think you’ll find it much easier to test your hook this way as it doesn’t require you to try and mock the observables created in your custom hook from `watchQuery`.

Assuming your custom hook returns the `result` from your `useState`, and that you can get access to that result from your `getHookResult` helper, I’d recommend using Testing Library’s [`waitFor`](https://testing-library.com/docs/dom-testing-library/api-async/#waitfor) method to assert on the result of that hook. Testing this way allows you to avoid testing the [implementation details](https://kentcdodds.com/blog/testing-implementation-details) of your hook and instead test on the inputs/outputs.

This might look something like this (some code is made up since I don’t know the extent of your setup)

```auto
const mocks = [...]

// not sure how you hook up client to your hook, but make sure it uses this one
const client = new ApolloClient({
  cache: new InMemoryCache(),
  link: new MockLink(mocks)
});

const result = getHookResult(() => useCustomHook(...))

await waitFor(() => {
  expect(result).toEqual([
    // whatever shape your result should be
  ]);
});

```

_As a note of advice, I’d also recommend testing error states, for example, if one of your `items` queries fails. Make sure your hook can handle this._

* * *

One last thing I’d like to mention here. I see you’re using some of our internal helper functions in your test. While we do export these, I’ll just warn you that these undocumented utilities may change or break at any given time.

For example, I’d like to completely deprecate our `itAsync` function and use plain `async`/`await` in our tests, which means this function will disappear. I don’t have a timetable on this, but we want to be free to remove it at any time. If you rely too heavy on some of these undocumented utilities, you may find find these break over time.

This isn’t to say you can’t or shouldn’t use them, just more of a Use At Your Own Risk ™ instead 😄

Let me know if you have any more questions! Hopefully this helps steer you in the right direction.

---

<div class="post-metadata">

**Author:** ![Eric\_Zhang](https://sea1.discourse-cdn.com/flex019/user_avatar/community.apollographql.com/eric_zhang/32/4201_2.png) [@Eric\_Zhang](https://community.apollographql.com/u/Eric_Zhang)\
**Post date:** [April 17, 2023, 12:53pm UTC](https://community.apollographql.com/t/how-to-do-unit-test-for-watchquery-in-react/6154/5 "2023-04-17T12:53:50Z")

</div>

Thanks, It is really helpful. One more question:

In the `getHookResult `, it is using `MockedProvider`. All of my code is under ` ApolloProvider,`, I am using ` const client = useApolloClient();` to grab my client instance. From you example, I need create a new client instance. Will it make my test handled by the new client instance here?

---

<div class="post-metadata">

**Author:** ![jerelmiller](https://sea1.discourse-cdn.com/flex019/user_avatar/community.apollographql.com/jerelmiller/32/3314_2.png) [@jerelmiller](https://community.apollographql.com/u/jerelmiller)\
**Post date:** [April 17, 2023, 4:03pm UTC](https://community.apollographql.com/t/how-to-do-unit-test-for-watchquery-in-react/6154/6 "2023-04-17T16:03:25Z")

</div>

@Eric_Zhang ahh that makes things much easier. I didn’t see the `useApolloClient` usage in your original example so I wasn’t sure how you were getting access to `client`.

In that case, don’t follow what I did by creating the `client` in your test. `MockedProvider` will do that for you. Just make sure you’re able to pass the mocks from your test to your `getHookResult` function so that they can be used with `MockedProvider`.

---

<div class="post-metadata">

**Author:** ![Eric\_Zhang](https://sea1.discourse-cdn.com/flex019/user_avatar/community.apollographql.com/eric_zhang/32/4201_2.png) [@Eric\_Zhang](https://community.apollographql.com/u/Eric_Zhang)\
**Post date:** [April 17, 2023, 9:08pm UTC](https://community.apollographql.com/t/how-to-do-unit-test-for-watchquery-in-react/6154/7 "2023-04-17T21:08:42Z")

</div>

It works! Thanks a lot.

---

<div class="post-metadata">

**Author:** ![jerelmiller](https://sea1.discourse-cdn.com/flex019/user_avatar/community.apollographql.com/jerelmiller/32/3314_2.png) [@jerelmiller](https://community.apollographql.com/u/jerelmiller)\
**Post date:** [April 17, 2023, 9:09pm UTC](https://community.apollographql.com/t/how-to-do-unit-test-for-watchquery-in-react/6154/8 "2023-04-17T21:09:21Z")

</div>

Awesome! Glad to hear!

---

<div class="post-metadata">

**Author:** ![Justin\_Gonzalez](https://sea1.discourse-cdn.com/flex019/user_avatar/community.apollographql.com/justin_gonzalez/32/5359_2.png) [@Justin\_Gonzalez](https://community.apollographql.com/u/Justin_Gonzalez)\
**Post date:** [February 6, 2025, 8:49pm UTC](https://community.apollographql.com/t/how-to-do-unit-test-for-watchquery-in-react/6154/9 "2025-02-06T20:49:03Z")

</div>

Archived on February 6, 2025, 8:49pm UTC


