Guide: Unit Testing React Apollo Components with React Testing Library
Tags: react, graphql, testing, javascript
Published: 2019-12-28 22:33:08

In this post I will present you a quick guide how to test React components which use Apollo.

At first let's see how our component looks like:

```javascript
import React from 'react'
import gql from 'graphql-tag'
import { useQuery } from '@apollo/react-hooks'

export const POSTS_QUERY = gql`
  query Post($id: String!) {
    {
      post(id: $id) {
        title
        author
        description
      }
    }
  }
`

const Post = ({ postId )} => {
  const { loading, error, data } = useQuery(POSTS_QUERY, {
    variables: { id: postId },
  })

  if (loading) return null
  if (error) return `Error: ${error}`

  return (
    <div>
      <h3 data-testId="post-title">{data.post.title}</h3>
      <h4 data-testId="post-author">{data.post.author}</h4>
      <p data-testId="post-description">{data.post.description}</p>
    </div>
  )
}

export default Post
```

I always had issues with testing components which do not render desired value immediately. In our case Post component at first won't render anything, because it is in `loading` state.

Fortunately `react-testing-library` solves this problem for us. It allows us to wait for some element to be rendered.

On the other hand, Apollo has very useful `MockedProvider` component. Thanks to this component you can mock result of your queries. Let's take a look at the code.

```javascript
import React from 'react'
import { render, cleanup, findByTestId, findByText } from '@testing-library/react'
import { MockedProvider } from '@apollo/react-testing'

import Post, { POSTS_QUERY } from './Post'

const mocks = [
  {
    request: {
      query: POSTS_QUERY,
      variables: {
        id: 'postId',
      }
    },
    result: {
      data: {
        post: {
          title: 'title',
          author: 'author',
          description: 'description',
        }
      }
    }
  }
]

describe('Post', () => {
  afterEach(cleanup)

  it('should render post title', async () => {
    const { container ) = render(
      <MockedProvider mocks={mocks} addTypename={false}>
        <Post postId="postId" />
      </MockedProvider>
    )

    const titleElement = await findByTestId(container, 'post-title')
    const titleContent = await findByText(titleElement, 'title')

    expect(titleElement).toBeTruthy()
    expect(titleContent).toBeTruthy()
  })

  ...tests for author and description
})
```

At first we create mocked query response for `POSTS_QUERY`. We pass the `mocks` variable to `MockedProvider` when rendering our component.

To get title element we use `findByTestId` function. When you go back to component code you can see we added `data-testId` to `h3` element.
When we finally find this element we check whether it has expected text using `findByText`.

### Additional resources
[Apollo Docs - Testing React components](https://www.apollographql.com/docs/react/development-testing/testing/)
[React Testing Library Docs](https://testing-library.com/docs/react-testing-library/intro)

---

I'm regularly publishing my insights on web development. 
Consider [subscribing to my newsletter](https://slawkolodziej.com/newsletter).
Visit my blog at [slawkolodziej.com](https://slawkolodziej.com) to find out more interesting content.
Follow me on [Twitter](https://twitter.com/slawkolodziej).