はじめに
テストコード作成中、Vitest + React Testing Library の挙動に悩まされました。
同じコンポーネントを1回しか描画していないつもりなのに、要素が2回出力され、テストが失敗する という問題が発生しました。
問題のコード
const mockArticle = {
id: "test-id",
title: "Test Article",
date: "2026-02-08",
url: "https://example.com",
thumbnail: "https://example.com/thumb.png",
};
describe("ArticleCard", () => {
test("タイトルが表示される", () => {
render(<ArticleCard article={mockArticle} />);
expect(screen.getByText("Test Article")).toBeInTheDocument();
});
test("日付が表示される", () => {
render(<ArticleCard article={mockArticle} />);
screen.debug();
expect(screen.getByText("2026-02-08")).toBeInTheDocument();
});
});
発生したエラー
TestingLibraryElementError: Found multiple elements with the text: 2026-02-08
このエラーは 「同じ日付が2回表示されている」=「DOMに ArticleCard が2個残っている」 ことで起きています。
つまり、
• 1つ目の test で render() した結果が DOM に残ったまま
• 2つ目の test でもう一回 render() して、2026-02-08 が2つになり getByText が「1個に決められない」
→ エラー
getByText は要素が1つだけ存在することを前提としているため、同じテキストを持つ要素が複数ある場合はエラーになります。
今回は表示回数を確認したいのではなく、「要素が表示されているか」だけを確認したいため、このエラーは意図しない挙動でした。
原因
原因は Vitest 自体ではなく、
React Testing Library の自動 cleanup が有効になっていなかったことでした。
React Testing Library は通常、各テスト後に DOM を自動で cleanup します。
しかし Vitest を使用する場合、Testing Library のセットアップを
明示的に読み込まないと、この自動 cleanup は実行されません。
その結果、1つ目の test で render された DOM が残ったまま、
2つ目の test が実行され、同じ日付を持つ要素が複数存在する状態になっていました。
解決策
各テスト後に cleanup が実行されるよう、共通のセットアップファイルに cleanup 処理を書く対応をしました。
セットアップ手順
1. セットアップファイルの作成
Vitest では Testing Library のセットアップを明示的に読み込まないと
自動 cleanup が有効にならないため、ここで cleanup を定義しています。
import "@testing-library/jest-dom/vitest";
import { cleanup } from "@testing-library/react";
import { afterEach } from "vitest";
// 各テスト後にクリーンアップ実行
afterEach(() => {
cleanup();
});
2. vitest.config.mts に設定
export default defineConfig({
test: {
setupFiles: ["./setupTests.ts"],
},
});
終わりに
Vitest自体が cleanup しないわけではなく、Testing Library の自動 cleanup を有効にするためのセットアップが必要でした。
Vitestでは「明示的なセットアップが必要」という点を
理解しておかないと、今回のような問題に遭遇することがあると学びました。
参考記事