React Testing LibraryとJestを使ってカスタムフックのテストコードを書いてみる

JavaScript

<script>” title=”<script>

<script>

Reactを使って開発をしていると、役割を分割するためにカスタムフックを書く場面があるかと思います。

今回はそのカスタムフックの簡単なテストコードをReact Testing LibraryとJestを使って書いてみます。

テスト対象コードの作成

まずは下記のような簡単なカウンターを実装します。

//Counter.tsx
import { useCounter } from "../hooks/useCounter";

export const Counter = () => {
  const { count, increment, decrement } = useCounter();

  return (
    <div>
      <h1>{count}</h1>
      <button onClick={() => decrement()}>-</button>
      <button onClick={() => increment()}>+</button>
    </div>
  );
};
//useCounter.tsx
import { useState } from "react";

export type props = {
  initialCount?: number;
};

export const useCounter = ({ initialCount = 0 }: props = {}) => {
  const [count, setCount] = useState(initialCount);
  const increment = () => setCount(count + 1);
  const decrement = () => setCount(count - 1);
  return { count, increment, decrement };
};

useCounterカスタムフック

useStateを使ってカウンターの状態を管理します。この状態はcountとして保持され、初期値はinitialCount(デフォルトは0)です。

Counterコンポーネント

useCounterカスタムフックを使用して、カウンターの状態(count)と操作関数(incrementdecrement)を取得します。

テスト①:initialCount(0)が出力されるか

//useCounter.test.ts

import { renderHook } from "@testing-library/react"
import { useCounter } from "./useCounter"

describe('useCounter', () => {
  test('initialCount(0)が出力されるか', () => {
    const {result} = renderHook(useCounter)
    expect(result.current.count).toBe(0)
  })
})

renderHook

@testing-library/react-hooksからインポートされ、Reactのカスタムフックを単独でレンダリングし、テストする機能を提供します。

renderHookは指定されたカスタムフック(今回の場合はuseCounter)をレンダリングし、その結果をresultオブジェクトに格納します。これにより、フックの返り値にアクセスしてテストを行うことができます。

公式ドキュメント: renderHook

describe関数

describeはJestの関数で、関連するテストをグループ化します。今回は「useCounter」という名前のグループ内でテストを実行しています。

test関数

testは個々のテストケースを定義するJestの関数です。itと書くこともあります。

expect(result.current.count).toBe(0)

expectとtoBeを用いたアサーション(期待値チェック)です。expect関数で設定した値と、toBeの引数に指定された値が完全に一致するかどうかを検証しています。

公式ドキュメント:toBe

テスト②:incrementが正しく動くか

import { act } from "react-dom/test-utils"

//省略

test('incrementが正しく動くか', () => {
    const {result} = renderHook(useCounter);
    act(() => { result.current.increment()})
    expect(result.current.count).toBe(1)
 })

先ほどの「initialCount(0)が出力されるか」のテストの続きに記載してください。

act関数

react-dom/test-utilsからインポートされ、主にコンポーネントの状態更新やライフサイクルイベントをテスト中に正確にシミュレートするために使用します。特にユーザーの操作やデータの更新など、状態の変化を伴う処理をテストする際に役立ちます。

公式ドキュメント:act

expect(result.current.count).toBe(1)

increment関数が呼ばれた後のcountの値が1になっていることを検証します。初期値が0であるため、プラス1した1であることを期待しています。

テスト③:decrementが正しく動くか

test('decrementが正しく動くか', () => {
    const {result} = renderHook(useCounter);
    act(() => { result.current.decrement()})
    expect(result.current.count).toBe(-1)
  })

incrementのテストと同様、act関数を使ってテストします。

expect(result.current.count).toBe(-1)

decrement関数が呼ばれた後のcountの値が-1になっていることを検証します。初期値が0であるため、マイナス1した-1であることを期待しています。

以上がReact Testing LibraryとJestを使ったカスタムフックのテストになります。