Closed3

react hook のテストコードサンプル集

ShinkawaShinkawa

関数Aを実行するとstateXXXに変化することを確認するケース

実装

import { useState } from "react";

export const useCounter = () => {
  const [count, setCount] = useState(0);
  
  const increment = () => {
    setCount(count + 1);
  };


  return {
    count,
    increment,
  };
};

テストコード

import { describe, expect, it } from "@jest/globals";
import { renderHook, act } from "@testing-library/react";
import { useCounter } from "./useConter";

describe("useCounter", () => {
  it("incrementを実行するとcountが1増えること", () => {
    const { result } = renderHook(() => useCounter());
    
    // 初期値は0であること
    expect(result.current.count).toBe(0); 

    act(() => {
      result.current.increment();
    })
    expect(result.current.count).toBe(1);
  });
});

point

import { renderHook, act } from "@testing-library/react"; // hook のテストに使うライブラリ


    const { result } = renderHook(() => useCounter()); // フックの呼び出し方。result.currentに現在の返り値が格納される。

act(() => { // stateの変更はactの中で行う
      result.current.increment();
    })

ShinkawaShinkawa

特定の条件下でとある関数が呼ばれることを確認するケース

export const hoge = () => {
    console.log("hoge だよ")
}
import { useState } from "react";
import { hoge } from "./hoge";

export const useCounter = () => {
  const [count, setCount] = useState(0);
  
  const increment = () => {
    const newCount = count + 1;
    setCount(newCount);
    if (newCount === 3) {
      hoge()
      return
    }
    
  };

  return {
    count,
    increment,
  };
};

import { describe, expect, it } from "@jest/globals";
import { renderHook, act } from "@testing-library/react";
import { useCounter } from "./useConter";
import * as hoge from "./hoge";

describe("useCounter", () => {
  it("countが3の時に、hoge()が呼ばれること", () => {
    const hogeSpy = jest.spyOn(hoge, "hoge");
    const { result } = renderHook(() => useCounter());
    expect(result.current.count).toBe(0);

    act(() => {
      result.current.increment();
    });
    // countが1になる時はhoge()が実行されないこと
    expect(hogeSpy).toHaveBeenCalledTimes(0); // or not.toHaveBeenCalled();

    act(() => {
      result.current.increment();
    });
    // countが2になる時はhoge()が実行されないこと
    expect(hogeSpy).toHaveBeenCalledTimes(0); // or not.toHaveBeenCalled();

    act(() => {
      result.current.increment();
    });
    // countが3になる時はhoge()が実行さること!!
    expect(hogeSpy).toHaveBeenCalledTimes(1); // or toHaveBeenCalled();

    act(() => {
      result.current.increment();
    });
    // countが4になる時はhoge()が実行されないこと
    expect(hogeSpy).toHaveBeenCalledTimes(1);
  });
});

ShinkawaShinkawa

APIリクエストがあるケース

import { useState } from "react";
import { hoge } from "./hoge";
import axios from "axios";

export const useCounter = () => {
  const [count, setCount] = useState(0);
  const [users, setUsers] = useState([]);

  const increment = async () => {
    const newCount = count + 1;
    setCount(newCount);
    if (newCount === 3) {
      hoge();
      return;
    }
    if (newCount === 4) {
      const users = await axios
        .get("https://jsonplaceholder.typicode.com/posts/1")
        .then((res) => res.data);
      setUsers(users);
      return;
    }
  };

  return {
    count,
    increment,
    users,
  };
};
import { describe, expect, it } from "@jest/globals";
import { renderHook, act, waitFor } from "@testing-library/react";
import { useCounter } from "./useConter";
import * as hoge from "./hoge";
import axios from "axios";

jest.mock("axios");
afterEach(() => {
  jest.clearAllMocks();
});

describe("useCounter", () => {
  it("countが4になる時に、ユーザー情報取得APIを実行し、レスポンスをusersにセットすること", async () => {
    const users = [{ name: "AAA" }];
    const resp = { data: users };
    (axios.get as jest.Mock).mockImplementation(() => Promise.resolve(resp));
    const { result } = renderHook(() => useCounter());
    expect(result.current.count).toBe(0);

    act(() => {
      result.current.increment();
    });
    act(() => {
      result.current.increment();
    });
    act(() => {
      result.current.increment();
    });
    expect(result.current.count).toBe(3);
    act(() => {
      result.current.increment();
    });
    waitFor(() => {
      expect(result.current.users).toEqual([]);
      expect(result.current.count).toBe(4);
      expect(axios.get).toHaveBeenCalled();
    });
  });
});

このスクラップは2023/11/22にクローズされました