2
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?

【Vitest】mockClear()とmockReset()

2
Last updated at Posted at 2026-04-09

はじめに

こんにちは!POMです。
React×TypeScriptで個人開発アプリを実装していて、
Vitestでのテスト実装中につまづいたことがあったので
備忘録として記録します。

問題

とある美容系の記録アプリの一覧画面(タイムライン形式)で
表示などの確認テストを下記のように実装していました。

/src/__tests__/Timeline.spec.tsx
const { mockFetchLogs } = vi.hoisted(() => {
    return {
        mockFetchLogs: vi.fn(),
    };
});

vi.mock("@/api/logs", () => ({
    fetchLogs: mockFetchLogs,
}));

describe("Timeline", () => {
    beforeEach(() => {
        mockFetchLogs.mockClear();
    });

    test("タイトル/カテゴリー/店舗名/担当者名/実施日/金額が表示されていること", async () => {
        mockFetchLogs.mockResolvedValue([{
            after_photo_url: null,
            before_photo_url: null,
            category: "nail",
            cost: 1000,
            created_at: "2026-04-09 09:16:52.56655+00",
            detail: "テストです",
            done_at: "2026-04-09",
            id: "test-id",
            next_interval_days: null,
            salon_name: "test salon",
            staff_name: "テスト花子さん",
            title: "テストタイトル",
            user_id: "test-user-id",
        }]);
        render(<TimelinePage />);
        
        expect(await screen.findByText("テストタイトル")).toBeInTheDocument();
        expect(screen. getByText("ネイル")).toBeInTheDocument();
        expect(screen.getByText("test salon")).toBeInTheDocument();
        expect(screen.getByText("担当者:テスト花子さん")).toBeInTheDocument();
        expect(screen.getByText("4/9")).toBeInTheDocument();
        expect(screen.getByText("¥1,000")).toBeInTheDocument();
    });



    test("記録がない場合にメッセージが表示されること", async () => {
        render(
            <TimelinePage />
        );
        const message = await screen.findByText("まだ記録がありません");
        expect(message).toBeInTheDocument();
    });

})

こちらでnpm run testしたところ、

 FAIL  src/__tests__/Timeline.spec.tsx > Timeline > 記録がない場合にメッセージが表示されること
TestingLibraryElementError: Unable to find an element with the text: まだ記録がありません. This could be because the text is broken up by multiple elements. In this case, you can provide a function for your text matcher to make your matcher more flexible.

どうやら1つ目の、タイトル等が表示されているかのテストで
モックとして実装していたものが、
2つ目のテストでも引き継がれており、
記録が無い状況を作り出せていなかったようです。

解決方法

beforeEach内部を下記のように修正しました。

    beforeEach(() => {
-        mockFetchLogs.mockClear();
+        mockFetchLogs.mockReset();
+        mockFetchLogs.mockResolvedValue([]); // 空配列に戻す
    });

公式ドキュメントを見ると
mockClearについては以下のように書かれています。

Clears all information about every call. After calling it, all properties on .mock will return to their initial state. This method does not reset implementations. It is useful for cleaning up mocks between different assertions.

clear call history but keep mock implementation

呼び出しに関する履歴はクリアするが、モック実装は保持する
といったことが書かれており、今回でいうと
1つ目のテストにおいてmockResolvedValueで設定した戻り値の実装が残るため、2つ目のテストで「まだ記録がありません」と表示されず失敗していました。

一方でmockResetについては、公式ドキュメントに
以下のように書かれております。

Does what mockClear does and resets the mock implementation. This also resets all "once" implementations.
Note that resetting a mock from vi.fn() will set the implementation to an empty function that returns undefined. Resetting a mock from vi.fn(impl) will reset the implementation to impl.
This is useful when you want to reset a mock to its original state.

mockClear()と同様の動作を行い、モックの実装をリセットする
とのことで、今回はmockReset()に修正したところ、
2つ目のテストにモックの実装が残らないようにすることができました。

おわりに

個人開発していると今まで使ったことのある実装に頼って
挙動が思うようにいかないことがありますね。
ちゃんとドキュメントを読むようにしましょう(自戒)

参考記事

JISOUのメンバー募集中!

プログラミングコーチングJISOUでは、新たなメンバーを募集しています。
日本一のアウトプットコミュニティでキャリアアップしませんか?
興味のある方は、ぜひホームページをのぞいてみてくださ!
▼▼▼

2
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
2
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?