はじめに
こんにちは!Halです!
Vitestでテストケース、主にモックを作成した際に発生した次のエラーについて解決方法をまとめていきます。
[vitest] No "createStudyRecord" export is defined on the "@/api/study-record-query" mock.
Did you forget to return it from "vi.mock"?
発生した状況
-
@/api/study-record-query
モジュールにはgetLatestStudyRecords
、deleteStudyRecord
、createStudyRecord
、updateStudyRecord
の4つの関数がexportされている - テストでは
getLatestStudyRecords
とdeleteStudyRecord
の2つの関数のみを使用 - 使用しない
createStudyRecord
はモック化したくないのに、なぜかこの関数もモック化を要求されるエラーが発生
問題
自分の状況として、「テストで必要なのは getLatestStudyRecords
と deleteStudyRecord
だけなのに、なぜか createStudyRecord
もモック化しないとエラーになる...」
といったことが起きており、モジュール内のすべての関数をモック化するのではなく、使用する関数のみモック化したいと考えていました。
理想的なモック(これがしたかった)
//これだけでテストしたいのに...
vi.mock("@/api/study-record-query", () => ({
getLatestStudyRecords: vi.fn(), // テストで使う
deleteStudyRecord: vi.fn(), // テストで使う
// createStudyRecord は使わないからモック化したくない
}));
現実
Error: No "createStudyRecord" export is defined on the mock
解決方法
部分モック(importOriginal)を使用
スプレッド構文を使用して、モジュール内の関数をモック化するもの、行わないものと振り分ける書き方を使用するものです。
メリット:
- 必要な関数だけモック化
- 他の関数は実際のコードが動く
- テストの意図が明確になる点
vi.mock(import("@/api/study-record-query"), async (importOriginal) => {
const actual = await importOriginal();
return {
...actual, // 元の実装を保持
getLatestStudyRecords: vi.fn(), // この関数だけモック
deleteStudyRecord: vi.fn(), // この関数だけモック
// createStudyRecord は actual から来る(元の実装)
};
});
おわりに
「使いたい関数だけモック化したい」という要求は、部分モック(importOriginal使用)で解決できます。この方法なら、不要な関数のモック化を強制されることなく、テストに必要な部分だけを制御できます。
参考
JISOUのメンバー募集中!
プログラミングコーチングJISOUでは、新たなメンバーを募集しています。
日本一のアウトプットコミュニティでキャリアアップしませんか?
興味のある方は、ぜひホームページをのぞいてみてくださ!
▼▼▼