How to Test Component Functions In React Testing Library

Ferenc Almasi β€’ 2022 September 14 β€’ πŸ“– 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.

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>
    )
}
Copied to clipboard!

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.

Looking to improve your skills? Check out our interactive course to master JavaScript from start to finish.
Master JavaScript

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:

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')
    })
})
Copied to clipboard!

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 Unlimited access to hundred of tutorials
  • check Access to exclusive interactive lessons
  • check Remove ads to learn without distractions
Become a Pro

Recommended