0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【React】Testing Library における waitFor と act の違い

Posted at

はじめに

こんにちは。アメリカ在住で独学エンジニアを目指している Taira です。
React Testing Library を使っていると、

  • waitForact ってどう違うの?」
  • 「どっちを使えばいいの?」

と迷うことがあると思います。

結論から言うと:

  • act = React の 副作用が終わってから確認するためのラッパー
  • waitFor = 非同期処理が落ち着いて「最終状態」になるまで待つためのユーティリティ

この2つの違いをシンプルに整理します。


act とは

  • React 公式が提供する低レベル API。
  • **「状態更新と副作用が終わるまで待ってから次の処理に進む」**ことを保証します。
import { act } from "react-dom/test-utils";

act(() => {
  counter.increment(); // setState
});

// 副作用が完了してから確認できる
expect(screen.getByText("count: 1")).toBeInTheDocument();

👉 副作用が完了した「あと」に確認するためのもの
Testing Library の renderuserEvent は内部で必要に応じて act を呼んでくれるので、通常はあまり意識しなくてOKです。
ただし 外部ストアの直接更新フェイクタイマー進行などは自動で包まれないため、手動で act を書く必要があります。


waitFor とは

  • Testing Library が提供するユーティリティ。
  • 非同期処理で「最終的に UI がどうなるか」をリトライしながら待つ
  • Promise を返すので await が必須。テスト関数自体も async にする必要があります。
test("保存メッセージが表示される", async () => {
  render(<SaveButton />);

  await user.click(screen.getByRole("button", { name: "保存" }));

  // await を忘れるとテストが正しく動かない
  await waitFor(() => {
    expect(screen.getByText("保存しました")).toBeInTheDocument();
  });
});

👉 単純に「要素が現れるのを待つ」なら findBy* を優先し、
複雑な非同期処理をまたぐ場合にだけ waitFor を使うのがおすすめです。


使い分けの目安

  • ユーザー操作や要素の表示待ちfindBy* / waitForElementToBeRemoved
  • 複雑な非同期処理で「最終状態」を待ちたいwaitFor(必ず await を付ける)
  • 外部ストア更新やタイマー進行など、副作用が終わるのを待ちたいact を明示的に

具体例

waitFor を使うケース

test("カウントが5になる", async () => {
  render(<Counter />);

  await waitFor(() => {
    expect(screen.getByRole("status")).toHaveTextContent("count: 5");
  });
});

act を使うケース(タイマー)

test("debounce 入力", () => {
  vi.useFakeTimers();
  render(<DebouncedInput />);

  user.type(screen.getByRole("textbox"), "hello");

  // タイマー進行は act で包む
  act(() => {
    vi.runAllTimers();
  });

  expect(screen.getByText("value: hello")).toBeInTheDocument();
});

まとめ

  • act = React の副作用が終わるのを待ってから確認する

  • waitFor = 非同期で UI が最終状態になるまでリトライして待つ

    • await を付けるのを忘れない!テスト関数も async 必須
  • 実際のテストでは

    • まず findBy* / userEvent を使う
    • 必要に応じて waitFor
    • それでも警告が出るときに act を明示的に使う
0
0
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
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?