[Jest] FAQ

テスト対象の中でimportしているモジュールのMockを作りたい

companyService.fetchclients/apiを使っているケース。
clients/apiをMock化して、副作用の無い状態でcompanyService.fetchをテストしたい。

jest.mockでモック化すれば、それをimportしている箇所全てに影響が出る。

import * as companyService from './company';
import * as api from '../clients/api';
jest.mock('../clients/api');

describe('companyService.fetch', () => {
  beforeAll(() => {
    (svn as any).list.mockReturnValue(['dummy1', 'dummy2']);
  });
  test('テスト', async () => {
    const actual = await companyService.fetch();
    expect(actual).toStrictEqual(['dummy1, dummy2']);
  });
});

モック化したモジュール.プロパティに対して、mockReturnValue(...)で任意の値をreturnさせる。
mockImplementation((arg1, arg2) => arg1 + arg2)のようにすると任意のfunctionを定義できる。

Decorators are not enabled エラーになる

エラーケース1

以下の場合

If you are using ["@babel/plugin-proposal-decorators", { "legacy": true }], make sure it comes *before* "@babel/plugin-proposal-class-properties" and enable loose mode, like so:
    ["@babel/plugin-proposal-decorators", { "legacy": true }]
    ["@babel/plugin-proposal-class-properties", { "loose": true }]

babel.config.jsplugins配下を以下の順で定義する。
順番が違うと動かない。

{
  "plugins": [
    ["@babel/plugin-proposal-decorators", { "legacy": true }],
    ["@babel/plugin-proposal-class-properties", { "loose" : true }]
  ]
}

legacyとlooseの理由を調べる

もちろん該当pluginのインストールは必要。

エラーケース2

以下の場合

Namespaces are not supported.

TypeScriptのnamespaceにデフォルトで対応していないから。

babel.config.jsplugins配下に以下を追加する。

  "plugins": [
    ["@babel/plugin-transform-typescript", {"allowNamespaces": true}],
  ]

デフォルトでは allowNamespaces: false なので明示的指定が必要。
将来はtrueになるらしい。

もちろん該当pluginのインストールは必要。

electronからimportできずエラーになる

Jestはmainを通してelectronを起動していないので当然失敗する。
処理がテストに関係なければ、Mockを作って凌ぐ。

package.json

  # moduleNameMapperに追加
  "jest": {
    "moduleNameMapper": {
      "electron": "<rootDir>/electron-mock.ts"
    }
  }

electron-mock.ts

# `{remote.require("exec").exec`まで呼ばれることを想定
export const remote = {
  require: (required_but_ignored: string) => ({
    exec: undefined
  })
};