|
| 1 | +--- |
| 2 | +id: testing |
| 3 | +title: Testing |
| 4 | +--- |
| 5 | + |
| 6 | +React Query works by means of hooks - either the ones we offer or custom ones that wrap around them. |
| 7 | + |
| 8 | +Writing unit tests for these custom hooks can be done by means of the [React Hooks Testing Library](https://react-hooks-testing-library.com/) library. |
| 9 | + |
| 10 | +Install this by running: |
| 11 | + |
| 12 | +```sh |
| 13 | +npm install @testing-library/react-hooks react-test-renderer --save-dev |
| 14 | +``` |
| 15 | + |
| 16 | +(The `react-test-renderer` library is needed as a peer dependency of `@testing-library/react-hooks`, and needs to correspond to the version of React that you are using.) |
| 17 | + |
| 18 | +## Our First Test |
| 19 | + |
| 20 | +Once installed, a simple test can be written. Given the following custom hook: |
| 21 | + |
| 22 | +``` |
| 23 | +export function useCustomHook() { |
| 24 | + const { data } = useQuery('customHook', () => 'Hello'); |
| 25 | + return data; |
| 26 | +} |
| 27 | +``` |
| 28 | + |
| 29 | +We can write a test for this as follows: |
| 30 | + |
| 31 | +``` |
| 32 | +const queryCache = new QueryCache(); |
| 33 | +const wrapper = ({ children }) => ( |
| 34 | + <ReactQueryCacheProvider queryCache={queryCache}> |
| 35 | + {children} |
| 36 | + </ReactQueryCacheProvider> |
| 37 | +); |
| 38 | +const { result } = renderHook(() => useCustomHook(), { wrapper }); |
| 39 | +expect(result.current).toEqual('Hello'); |
| 40 | +``` |
| 41 | + |
| 42 | +Note that we provide a custom wrapper that builds the `QueryCache` and `ReactQueryCacheProvider`. This helps to ensure that our test is completely isolated from any other tests. |
| 43 | + |
| 44 | +It is possible to write this wrapper only once, but if so we need to ensure that the `QueryCache` gets cleared before every test, and that tests don't run in parallel otherwise one test will influence the results of others. |
| 45 | + |
| 46 | +## Testing Network Calls |
| 47 | + |
| 48 | +The primary use for React Query is to cache network requests, so it's important that we can test our code is making the correct network requests in the first place. |
| 49 | + |
| 50 | +There are plenty of ways that these can be tested, but for this example we are going to use [nock](https://www.npmjs.com/package/nock). |
| 51 | + |
| 52 | +Given the following custom hook: |
| 53 | + |
| 54 | +``` |
| 55 | +function useFetchData() { |
| 56 | + const { data } = useQuery('fetchData', () => request('/api/data')); |
| 57 | + return data; |
| 58 | +} |
| 59 | +``` |
| 60 | + |
| 61 | +We can write a test for this as follows: |
| 62 | + |
| 63 | +``` |
| 64 | +const queryCache = new QueryCache(); |
| 65 | +const wrapper = ({ children }) => ( |
| 66 | + <ReactQueryCacheProvider queryCache={queryCache}> |
| 67 | + {children} |
| 68 | + </ReactQueryCacheProvider> |
| 69 | +); |
| 70 | +const expectation = nock('http://example.com') |
| 71 | + .get('/api/data') |
| 72 | + .reply(200, { |
| 73 | + answer: 42 |
| 74 | + }); |
| 75 | +const { result, waitFor } = renderHook(() => useFetchData(), { wrapper }); |
| 76 | +await waitFor(() => { |
| 77 | + return result.current.isSuccess(); |
| 78 | +}); |
| 79 | +expect(result.current).toEqual({answer: 42}); |
| 80 | +``` |
| 81 | + |
| 82 | +Here we are making use of `waitFor` and waiting until our Nock expectation indicates that it has been called. This way we know that our hook has finished and should have the correct data. |
0 commit comments