Testing Functions within Functional React Components
Tags: testing, react
Published: 2022-06-02 22:29:44

People are switching to functional components in React, and class-based components are quickly becoming a thing of the past. However, with class-based components out of the picture, it’s much harder to access a function *within* your functional component for [unit testing](https://dev.to/bonnie/when-to-unit-test-your-react-app-4659). A common question I get these days:

> How do I test functions inside my functional component?

The short answer: *you can’t*. There is no way to access functions defined within a functional component for testing. But… if you’re reading this post, you probably don’t like that answer. Read on to see what your options are. 😊

## Option 1: Don’t unit test the functions

Do any or all of the functions **need** to be unit tested? The trend in React testing these days is *functional* or *behavioral* testing, which means testing the interface between your app and your user. Unit testing functions means you’re testing internals (that is, testing your code, instead of testing your app). This is generally frowned upon because it makes your tests brittle and subject to rewriting upon refactor.

However, there are some cases where unit testing functions can be beneficial (for complex functions, or functions with edge cases that don’t affect the display layer). You can see [this blog post](https://bonniedotdev.medium.com/when-to-unit-test-your-react-app-f5b211eb41c9) for my recommendations on when to unit test within React apps. If these reasons fit your situation, take a look at the other options.

## Option 2: Move Functions Outside the Component

Relocating functions to a [custom hook](https://reactjs.org/docs/hooks-custom.html) makes them accessible for testing (plus you’re keeping business logic separate from the UI, in accordance with best practices). There’s even a library to help with testing custom hooks: [react-hooks-testing-library](https://github.com/testing-library/react-hooks-testing-library).

Here’s [an example of a custom hook with several related functions](https://github.com/bonnie/bonniedotdev/blob/5513fd5ff3384e44e396b33b6d477ce4788d462e/client/src/Hooks/useFilterTags.ts) in my [website](https://bonnie.dev) code. Note that I don’t test this particular hook separately from the UI because it fits under this category in “[When not to use the react-hooks library](https://github.com/testing-library/react-hooks-testing-library#when-not-to-use-this-library)” : *Your hook is easy to test by just testing the components using it.*

Still, it’s an example of removing functionality from the functional component, so the component can focus solely on display. And I **could** access the functions within the hook for testing if they matched the [reasons to use the react-hooks library](https://github.com/testing-library/react-hooks-testing-library#when-to-use-this-library):

1.  You’re writing a library with one or more custom hooks that are not directly tied to a component
2.  You have a complex hook that is difficult to test through component interactions

## Option 3: Use Class-Based Components

This one might give you the heebie-jeebies — after all, you made a functional component to get **away** from the complexity of class-based components. However, you always have this option if the first two options don’t work for you. Class-based components served the React community well for many years, and they are still supported by React. And to the point of this blog post, you can easily access functions within a class-based component as a property of the component.

---
So there you have it: three options for testing functions within a functional component (none of which actually test functions within a functional component, since that’s just not possible).