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
)と操作関数(increment
、decrement
)を取得します。
テスト①: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
オブジェクトに格納します。これにより、フックの返り値にアクセスしてテストを行うことができます。
describe関数
describe
はJestの関数で、関連するテストをグループ化します。今回は「useCounter」という名前のグループ内でテストを実行しています。
test関数
test
は個々のテストケースを定義するJestの関数です。it
と書くこともあります。
expect(result.current.count).toBe(0)
expect
とtoBe
を用いたアサーション(期待値チェック)です。expect
関数で設定した値と、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
からインポートされ、主にコンポーネントの状態更新やライフサイクルイベントをテスト中に正確にシミュレートするために使用します。特にユーザーの操作やデータの更新など、状態の変化を伴う処理をテストする際に役立ちます。
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を使ったカスタムフックのテストになります。