📝

【Jest】テスト全体で共通化したモックを特定のテストファイルで利用しない方法

2023/01/27に公開

以前、テスト全体で使用する環境変数の設定方法について書きました。
https://zenn.dev/ncdc/articles/jest-environment

今回は、各テストファイルで共通的にモックを用意したい場合と、特定のテストファイルでは使用しないための設定を書きます。

やりたいこと

  • 各テスト共通的にモックを用意したい
    • 例えばAPIの認可メソッドなど
    • jwtなどからユーザ情報を取得するメソッドはAPIテストの際にはモック化したいので、テスト全体で認可メソッドのモックを作りたい
  • 認可メソッド自体のテストは行いたい
    • 認可メソッドのテストファイルではモックをアンマウントしたい
    • モック化したモジュールが返す中身をテストファイル毎に設定したいときがある

やり方

共通的にモックを用意する

jestの設定ファイルのsetupFilesまたは、setupFilesAfterEnvオプションを使用します。
モックを用意するファイルを指定します。
setupFilessetupFilesAfterEnvは各テストの実行前に実行したい処理を定義出来ます。
setupFilesAfterEnvは環境変数が読まれた後に実行されるため、環境変数を使用したモックを用意する場合はこちらを使用します。

jest.config.js

module.exports = {
  clearMocks: true,
  moduleFileExtensions: ["js", "jsx", "ts", "tsx", "node"],
  roots: ["<rootDir>/src"],
  testEnvironment: "node",
  transform: {
    "^.+\\.tsx?$": "ts-jest",
  },
  moduleNameMapper: {
    "^@/(.*)$": "<rootDir>/src/$1",
  },
  moduleDirectories: ["node_modules", "<rootDir>"],
  setupFiles: ["<rootDir>/src/tests/common.ts"], // モックを用意するファイルを指定
};

指定したファイルの中でモックを定義します。

common.ts

import AuthUserRepositoryImpl from "@/repository/AuthUserRepository";

jest.setTimeout(30000); // タイムアウトの時間を30秒に伸ばす

// トークンから認証ユーザを取得する処理をモック化
jest.mock("@/infra/repository/AuthUserRepository");
(AuthUserRepositoryImpl as jest.Mock).mockImplementation(() => {
  return {
    getAuthUser: () =>
      Promise.resolve({
        userId: 1,
        companyId: 1,
        email: "sample@example.com",
        userName: "taro",
        role: "admin",
      }),
  };
});

AuthUserRepositoryImplには、DBから認証ユーザを取得するメソッド(getAuthUser)が実装されています。
APIテストの場合、各テストでAuthヘッダを設定するのは面倒なのでテスト全体でモックを用意することが出来ます。

一部のファイルでモックをアンマウントする

モック化したモジュール自身や、モック化したモジュールを使用する場合(上の例だと認証情報を動的に変えたい場合)は、テスト時にjest.unmockを使用してモックをアンマウントします。

モック化したモジュールのテスト、またはモック化したモジュールを動的に変えたいファイル

import AuthUserRepositoryImpl from "@/repository/AuthUserRepository";

jest.unmock("@/infra/repository/AuthUserRepository"); // モックをアンマウント

// 新たにモックを定義する場合
jest.mock("@/infra/repository/AuthUserRepository");
(AuthUserRepositoryImpl as jest.Mock).mockImplementation(() => {
  return {
    getAuthUser: () =>
      Promise.resolve({
        userId: 1,
        companyId: 1,
        email: "sample@example.com",
        userName: "taro",
        role: "normal",  // 一般ユーザ権限でモックを定義
      }),
  };
});

以上です。

参考:
https://jestjs.io/docs/configuration#setupfiles-array
https://jestjs.io/docs/jest-object#jestunmockmodulename

GitHubで編集を提案
NCDCエンジニアブログ

Discussion