Image for post

Photo by Anna Hunko on Unsplash

Hooks are popular, as they bring readability and maintainability. Custom hooks become enablers for composability and reusability. In headless UI components, we explored custom hooks, along with high-order components (HOCs).

How can we test them? In Test Cases and Test Coverage for High Order Components, we gave examples on how to write test cases for high order components and how to measure test coverage, using the Jest and React Testing Library. In this article, we are going to demonstrate how to use React Hooks Testing Library to test custom hooks.


Install React Hooks Testing Library

There are two packages needed for testing custom hooks:

npm install --save-dev @testing-library/react-hooks
npm install --save-dev react-test-renderer

After the installation, these packages become [devDependencies](https://medium.com/better-programming/package-jsons-dependencies-in-depth-a1f0637a3129) in package.json.

Test Renderer (react-test-renderer) is used to render React components to pure JavaScript objects, without depending on the DOM or a native mobile environment. The installed version should match the React version.

@testing-library/react-hooks is built on top of Test Renderer.

You probably need other @testing-library packages too. If you use Create React App, they are part of dependencies in package.json:

"dependencies": {
  "@testing-library/jest-dom": "^4.2.4",
  "@testing-library/react": "^9.5.0",
  "@testing-library/user-event": "^7.2.1"
}

renderHook API

renderHook API is the center piece of @testing-library/react-hooks. It renders a test component that calls the provided callback, including any hooks it calls, every time it renders.

function renderHook(
  callback: function(props?: any): any,
  options?: RenderHookOptions
): RenderHookResult

options has the type of RenderHookOptions, which is an object that optionally includes:

  • initialProps: It is the initial value to the callback function of renderHook.
  • wrapper: It is a React component to wrap the test component while using global context.

RenderHookResult is a data structure defined as follows:

{
  current: any,
  error: Error
}

We are using examples to show how renderHook is used in various cases. Create React App is used as the working environment. All custom hooks are hosted in src/hooks, and all hook tests are hosted in src/hooks.test.js.

In Everyone Can Build a Custom Hook, we built a series of hooks. We are going to use them to build test cases.

This is the simplest hook:

The following are test cases:

At line 6, renderHook is used to render the custom hook, useMyName.

At line 7, result.current is the return value of useMyName.

Comparing to the case at lines 5 - 8, lines 10-13 show a different case with the initial value set to “Larry”.

As we have explained in the other article, the following command is used to execute the test cases:

npm test -- --testMatch="<rootDir>/src/hooks.test.js" --collectCoverage --collectCoverageFrom="src/hooks.js"

Here are the test results and test coverage:

Image for post


rerender API

In the previous tests, we repeated two tests with different initial values. This can be combined by passing the initial value to renderHook’s callback:

renderHook((initialName) => useMyName(initialName)

When the initial value changes, we call rerender to trigger the hook to be recalculated.

function rerender(newProps?: any): void

Here is the alternative test suite:

This produces the same results:

Image for post

Now, let’s take a look at a more complicated custom hook, which returns a method and a value.

Here are the test cases:

At line 6, renderHook is used to render the custom hook, useMyName. This time, current is destructured to a method and a value (line 12). The method is tested at line 13, and the message is tested at line 14 and line 16.

Run the test suite:

Image for post

#react-hook #reactjs #react #programming #javascript

Test Custom Hooks Using React Hooks Testing Library
21.35 GEEK