Guide: Unit Testing React Apollo Components with React Testing Library

thumbnail for Guide: Unit Testing React Apollo Components with React Testing Library

Testing components with async state was always tricky. Fortunately @testing-library/react-testing-library solves this problem for us. It allows us to wait for some element to be rendered.

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:

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.

Also, 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.

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 used data-testId in h3 element. When we finally find this element we check whether it has expected text using findByText.

Additional resources

Apollo Docs - Testing React components

React Testing Library Docs

You might also like

thumbnail for 7 Tips to Get Up to Speed Quickly in New Job or Project
November 9, 2020
7 Tips to Get Up to Speed Quickly in New Job or Project
Changing projects often taught me how to onboard quickly to new project and contribute as soon as possible.
thumbnail for Tailwind CSS: The future of styling or just another CSS framework?
January 15, 2021
Tailwind CSS: The future of styling or just another CSS framework?
Tailwind CSS looked like the first framework I would enjoy using. I already saw how easily you can create beautiful UIs with it (thanks to Tailwind UI project).
thumbnail for My 2020 In Review: What I Learned and Accomplished as Senior Front-end Developer
December 28, 2020
My 2020 In Review: What I Learned and Accomplished as Senior Front-end Developer
With 2020 coming to an end (finally!) I decided to do a little summary of things I learned during this year.

Hi friend,

Over the years working as a Front-end Developer in numerous projects I have gained a lot of experience. I've seen how choice of the right technology and architecture can affect the application and team behind it in a long run.

On this blog I want to share my experiance. I will show you solutions I discovered over the years. I want to teach you how to create better code and be successful developer.

Join the list of developers interested in web development

After signing up you will receive for free: Interview questions I ask as technical recruiter

newsletter