5
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

こぼのフロントエンドレビュー帳Advent Calendar 2022

Day 6

【React】カスタムフックのテストはこんな感じに書くといいよ

Last updated at Posted at 2022-12-07

はじめに

みなさんはフロントエンドのテストを書いているでしょうか?

書き始めると世界が変わりますよ
嘘ではなく、本当に開発スピードは上がるし、バグは減ります。

なぜテストを書くのかという話は以前書いたので、もし興味のある方は見てください

今回は、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を実行した後にはvaluetoggle()が返ってきます。

expect

検証にはexpectという構文を使います。
後ろにはマッチャーを書くことができ、今回の場合、.toBe(false)で返り値のvaluefalseであることを検証しています。

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に書き変わっていることが検証できます。

まとめ

今回はカスタムフックのテストということで、ざっくりとどう書いていけばいいのかについて記事にしてみました。
他にももう少し複雑なケースは、モックしないといけないケースなども出てきますので、またの機会に取り上げれればと思います。

5
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?