環境
- React + Typescript
- Jest 29.7
発生した問題
JestでsupabaseのAPIへのアクセスを行う関数をモック化しようとした際、モック化が行われずsupabaseへのアクセスが行われてしまった。
調査方法
ライブラリが動かない際は、
環境が悪いのかコードが悪いのかの原因を切り分ける必要があると教わりました。
なので、一度同じ設定ファイルを利用し、最小限でモックを動かすテストコードを作成しました。
// 実際にはsupabaseのアクセスを行う動作
export const sample = async() => {
console.log("モックではなく実動作をした");
return 0;
};
import { sample } from "../sample";
describe("モックお試し", () => {
it("テスト確認", async () => {
expect(true).toBeTruthy();
});
it("モック動作しない", async () => {
const mock = jest.fn().mockResolvedValue(Promise.resolve(1));
jest.mock("../sample", () => {
return {
sample: () => mock(),
};
});
// モック化が正しく行われていれば、このテストは失敗するはずですが、通過してしまいます。
expect(true).toBeTruthy();
sample().then((res) => {
expect(res).toBe(0);
});
});
});
原因
問題の原因は、jest.mock()の配置にありました。Jestのモック機能を正しく動作させるには、jest.mock()をファイルの先頭に配置する必要がありました。
import { sample } from "../sample";
const mock = jest.fn().mockResolvedValue(Promise.resolve(1));
jest.mock("../sample", () => {
return {
sample: () => mock(),
};
});
describe("モックお試し", () => {
it("テスト確認", async () => {
expect(true).toBeTruthy();
});
it("モック", async () => {
expect(true).toBeTruthy();
sample().then((res) => {
expect(res).toBe(1);
});
});
});
Jest公式ドキュメント( https://jestjs.io/ja/docs/mock-functions )もjest.mock()
は必ず先頭に記載しているようなので、ルールとして統一されているようです。
Claudeに聞いたらこんな回答が返ってきました。
Jest公式ドキュメント(モック関数)でも、jest.mock()は常にファイルの先頭に配置されています。これはJestの設計上の要件であり、モックの定義がモジュールのインポートよりも先に行われる必要があるためです。
最後に
公式ドキュメントを必ず参照すること
ライブラリのエラーで行き詰まった際は、必ず公式ドキュメントを参照することが重要です。特に「動作しない」というケースでは、公式の実装例を参考にすることが最も正確かつ効率的な解決方法となりました。
(これを行わずに1週間半ほど無駄にしていまいました…)
テストケースの中にjest.mock()を記述した意図
私がテストケースの中に記述したのは、テストケースごとにモックで返却する値を変えたかった…といった意図があり、素人考ながらこういった実装にしてしまいました。
正しい方法を確立できたらまた別記事にします。
ご拝読いただきありがとうございました。