ささきしき

チラシ

globalにexportした関数をjestでmockする【備忘】

ルー語か?(挨拶)

サンプルコードが胡乱なのは業務コード持ってきた誤魔化しがあるから勘弁してくれや。

マジな話すると以下のサイト見たらおわり

rinoguchi.net

tl;dr

import * as moduleName from '/path/to/module';
jest.spyOn(moduleName, 'functionName').mockReturnValue();

グローバル名前空間にエクスポートした関数(以下の例での prepareFn() )をjest空間でモックして使いたいとき、テストファイルになんと書くべきか問題。

// prepareFn.js

/**
 * 実際にはfetchで外部データを取り回したり、
 * なにがしかの複雑な中間処理があったりする想定
 */
export async function prepareFn (ctx) {
  return ctx.cond ? await doType1(ctx) : false;
}

async function doType1 (ctx) {
  // operation
}
// somethingDo.js

/**
 * prepareFn()の実行成否を前提とした関数のテストがしたいので、
 * そこだけモックに包めると助かる
 */
export async function somethingDo (ctx) {
  const cond = await prepareFn(ctx);
  cond && doHoge();
}

これに対してテストファイルでモック化したい場合、最も手っ取り早い方法はファイルトップで jest.mock('/path/to/prepareFn.js'); としてしまうものだが、この方法ではファイル内の全テストに対してモックが当たってしまう。

望まれるのは「テスト記述(test(), it())内で個別にモック化できる記法」だが、以下のように書くと良い。

// somethingDo.test.js

import * as prepareFn from '/path/to/prepareFn';
import { somethingDo } from '/path/to/somethingDo';

// 引数の型が合ってないのは適当に書いたからなので許してヒヤシンス
test('somethingDoテスト prepareFnモックしない', async () => {
  somethingDo('ʕ •ᴥ•ʔ'); 
});

test('somethingDoテスト prepareFn成功', async () => {
  jest
    .spyOn(prepareFn, 'prepareFn')
    .mockReturnValue(Promise.resolve(/*piyo*/));
  somethingDo('ʕ •ᴥ•ʔ'); 
});

test('somethingDoテスト prepareFn失敗', async () => {
  jest
    .spyOn(prepareFn, 'prepareFn')
    .mockReturnValue(Promise.reject(false));
  somethingDo('ʕ •ᴥ•ʔ'); 
});

Refer to

モック関数 · Jest