How to Test Component Functions In React Testing Library

Ferenc Almasi β€’ 2022 September 14 β€’ Read time 3 min read
  • twitter
  • facebook

How should I test a function inside a component in React Testing Library? The short answer is: you shouldn't. You might be thinking we need to mock the function and expect it to be called. However, this is not the correct approach. Instead, you should be testing behavior, and what a real user would see inside their browser.

For demonstration purposes, take the following component as an example which renders a dialog that can be toggled on and off using a useState hook.

Copied to clipboard! Playground
import { useState } from 'react'

export default function App() {
    const [toggled, setToggled] = useState(false)

    const toggle = () => {
        setToggled(!toggled)
    }

    return (
        <div>
            <dialog open={toggled} data-testid="dialog">Dialog</dialog>
            <button onClick={toggle}>Toggle</button>
        </div>
    )
}

Imagine we want to test the toggle function inside it to verify it toggles the correct state. However, you should avoid testing implementation details as they will make your test suite fragile. If your implementation changes, so do your tests, otherwise, they will break.


Testing Component Methods the Right Way

Instead of directly testing functions, we should be testing behavior β€” that is, whether the button toggles the correct attribute. This can be done in the following way in React Testing Library:

Copied to clipboard! Playground
import React from 'react'
import { fireEvent, render, screen } from '@testing-library/react'
import { Dialog } from '@components'

describe('Dialog', () => {
    it('should toggle the dialog on and off', () => {
        render(<Dialog />)

        const dialog = screen.getByTestId('dialog')
        const button = screen.getByRole('button')

        expect(dialog).not.toHaveAttribute('open')

        fireEvent.click(button)

        expect(dialog).toHaveAttribute('open')
    })
})

First, we grab the elements from the component using getByTestId and getByRole, then use the fireEvent API to trigger a click on the button. This will call the function, which means we can verify its effect on the open attribute on our dialog. Make sure you also verify the absence of the attribute prior to clicking the button.

Now we avoided directly testing implementation details of our functions defined inside our components, and instead tested how the component should behave. If you are interested in more unit test best practices, make sure you have a look at the article below.

11 Jest Best Practices to Get the Most Out of Your Tests
  • twitter
  • facebook
Did you find this page helpful?
πŸ“š More Webtips
Frontend Course Dashboard
Master the Art of Frontend
  • check Access 100+ interactive lessons
  • check Unlimited access to hundreds of tutorials
  • check Prepare for technical interviews
Become a Pro

Courses

Recommended

This site uses cookies We use cookies to understand visitors and create a better experience for you. By clicking on "Accept", you accept its use. To find out more, please see our privacy policy.