はじめに
今までJest を使っていましたが、はじめてVitest を導入してテストを書いたところ、
Jest と同じ書き方でモックを定義したらエラーに遭遇しました。
本記事では、Jest と Vitest でのモックの違いと、実際に解決した方法をまとめます。
Jest のモック作成方法
まず、Jest で useNavigate をモック関数に差し替える場合のコードです。
const mockedNavigator = jest.fn();
jest.mock("react-router-dom", () => ({
...jest.requireActual("react-router-dom"),
useNavigate: () => mockedNavigator,
}));
VitestでJest と同じように書いた場合のエラー
Jest と同じ感覚で Vitest に書き換えてみました。
const mockedNavigator = vi.fn();
vi.mock("react-router-dom", () => ({
...vi.requireActual("react-router-dom"),
useNavigate: () => mockedNavigator,
}));
しかし、以下のようなエラーが発生しました。
Property 'requireActual' does not exist on type 'VitestUtils'.
原因
Jest は CommonJS ベースで動作するため requireActual を使用しますが、Vitest は ESM(ESMAScript Modules)ベースで動作します。そのため、Vitest では CommonJS 用の requireActual は存在せず、代わりに ESM 向けの importActual を使用する必要があります。
ESM(ES Modules)と CJS(CommonJS)の違いについて詳しく知りたい方は、以下の記事が参考になります。
https://zenn.dev/medicalforce/articles/28a95c3c14aa9b
解決法
Vitest の場合は以下のように書きます。
const mockedNavigator = vi.fn();
vi.mock("react-router-dom", async () => {
const actual = await vi.importActual<typeof import("react-router-dom")>("react-router-dom");
return {
...actual,
useNavigate: () => mockedNavigator,
};
});
変更箇所
・vi.requireActual → vi.importActual に変更する。
・async と await をつける。(importActualは非同期処理だから)
・型を指定するように変更する。(typeof import("react-router-dom") を利用)
Jest と Vitest の違いまとめ
| 項目 | Jest | Vitest |
|---|---|---|
| モック関数 | jest.fn() | vi.fn() |
| 実モジュール読み込み | jest.requireActual("xxx") 同期 (CJS) |
vi.importActual("xxx") 非同期 (ESM, await が必要) |
終わりに
Jest の知識だけで書いてしまうと Vitest では思わぬエラーに遭遇しましたが、
調べてみることでVitestの書き方とモジュールシステム(CJS と ESM)の違いを理解するきっかけになりました。
参考