How to Test Component Functions In React Testing Library

Ferenc Almasi β€’ 2022 September 14 β€’ πŸ“– 3 min read

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.
JavaScript Course

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
JavaScript Course Dashboard

Tired of looking for tutorials?

You are not alone. Webtips has more than 400 tutorials which would take roughly 75 hours to read.

Check out our interactive course to master JavaScript in 5 hours.

Learn More

πŸ“š Get access to exclusive content

Want to get access to exclusive content? Support webtips with the price of a coffee to get access to tips, checklists, cheatsheets, and much more. β˜•

Get access Support us
Read more on
πŸŽ‰ Thank you for subscribing to our newsletter. x