はじめに
みなさんはフロントエンドのテストを書いているでしょうか?
書き始めると世界が変わりますよ
嘘ではなく、本当に開発スピードは上がるし、バグは減ります。
なぜテストを書くのかという話は以前書いたので、もし興味のある方は見てください
今回は、Reactのカスタムフックのテストをどのように書くのかという話をします。
Reactに対して、Jestでテストを書いていきます
サクッと環境を用意したい方は、Next.jsを使うのが良いと思います。
https://nextjs.org/docs/testing#jest-and-react-testing-library
Reactにおけるテストコード
大別すると2つあります。
- 単体テスト
- コンポーネントテスト
他にもE2Eテストやビジュアルリグレッションテストなど色々ありますが、まずは上記二つが重要になってきます。
単体(ユニット)テスト
ある程度小さめに切られた単位(ユニット)に対してテストを書いていく方法です。
通常のfunctionもそうですが、Reactではとりわけ、カスタムフックに対していかにテストコードを書いていくかということが重要になってくるかなと思います。
なので、のちにカスタムフックについてのテストコードも紹介しようと思います。
コンポーネントテスト
今回はコンポーネントテストについては触れませんが、
よりユーザーに近い動作のテストを書くことができます。
一つの小さなコンポーネントテストということで、単体テストと捉えられなくもないですが、結合テストに近いかなと個人的には思います。
カスタムフックのテスト
さて、ざっと概要を知ったところで、今回フォーカスを当てるカスタムフックのテストについて話します。
0. 概要を理解する
まず、カスタムフックというのは、基本、関数コンポーネントの中でしか動きません。
フック自体が関数コンポーネントにstateやeffectを起こすものになるので、当然ですね。
ではテストはどう書くのでしょうか?
関数コンポーネントの中で書く?
それだと単体テストではなく、上に説明したコンポーネントテストになってしまいますね。
なので、@testing-library/react
というライブラリを用い、擬似的に関数コンポーネントの中でカスタムフックを実行したかのように見せかけます。
下準備をする
何はともあれ、何をテストしたいのかを定めましょう。
今回は、簡単なトグルhooksを用意しました
import { useState } from "react";
export const useToggle = (initialValue: boolean) => {
const [value, setValue] = useState(initialValue);
const toggle = () => setValue((current) => !current);
return { value, toggle };
};
初期ステートがちゃんと入ることを検証する
先に紹介したrenderHook
を用い、カスタムフックを実行します。
describe('initial stateがfalseの時', () => {
it('stateがfalseである', () => {
const { result } = renderHook(() => useToggle(false));
expect(result.current.value).toBe(false);
});
...
});
result.current
renderHook
は色々返してくれますが、result
というところにhooksを実行した後の返り値をオブジェクトで渡してくれます。
今回で言うと、useToggle
を実行した後にはvalue
とtoggle()
が返ってきます。
expect
検証にはexpect
という構文を使います。
後ろにはマッチャーを書くことができ、今回の場合、.toBe(false)
で返り値のvalue
がfalse
であることを検証しています。
renderHookを実行したのち、toggle関数で値が変わることを検証する
次に、初期値を入れた後、toggle関数を実行して、実際に値が書き変わるか検証します。
ステートを変えるような処理を実行したい場合は、act
で囲む必要があります。
describe('initial stateがfalseの時', () => {
...
it('toggleを実行したらtrueに変わる', () => {
const { result } = renderHook(() => useToggle(false));
act(() => {
result.current.toggle();
});
expect(result.current.value).toBe(true);
});
});
これを実行すると、result.current
が変化し、expect
を用いれば値がtrue
に書き変わっていることが検証できます。
まとめ
今回はカスタムフックのテストということで、ざっくりとどう書いていけばいいのかについて記事にしてみました。
他にももう少し複雑なケースは、モックしないといけないケースなども出てきますので、またの機会に取り上げれればと思います。