Testing React Custom Hooks

Testing React Custom Hooks

·

2 min read

Prepare

We can use cra to create a basic react project easily.

npx create-react-app@latest react-demo-cra

Then we are ready to go.

Test useTitle

Say we have a custom hook called useTitle, which just update the title in the useEffect hook.

import { useEffect } from "react";

export default function useTitle(title) {
    useEffect(() => {
        document.title = title;
    });
}

For the hook to actually run, we need run it in a component to test it.

import { render } from "@testing-library/react";
import useTitle from "./useTitle";

test("useTitle", () => {
    const Component = () => {
        useTitle("test");
        return <div></div>;
    };
    render(<Component />);
    expect(document.title).toBe("test");
});

Actually, react testing library provides a simple method renderHook to run custom hooks. We we need to do is just pass it a callback, which calls the custom hook inside.

import { render, renderHook } from "@testing-library/react";
import useTitle from "./useTitle";

test("useTitle2", () => {
    renderHook(() => useTitle("test2"));
    expect(document.title).toBe("test2");
});

Test useValue

Now let see how to test a custom hook with states.

Below we define a custom hook useValue, which just define a state with useState hook.

import { useState } from "react";

export default function useValue(init) {
    const [value, setValue] = useState(init);
    return { value, setValue };
}

So how to test a hook like this? The renderHook function returns a value, which contains all the values the custom hook returns. Then we could assert on these values.

import { renderHook } from "@testing-library/react";
import { act } from "react-dom/test-utils";
import useValue from "./useValue";

test("useValue", () => {
    const { result } = renderHook(() => useValue("1"));
    expect(result.current.value).toBe("1");

    act(() => {
        result.current.setValue("2");
    });
    expect(result.current.value).toBe("2");
});

Note that if we want to call the functions the custom hook returns, we need to wrap them in the act function.