jestで関数をモックにして複数回テストしたときに、expectが意図しない結果になるパターン


まずはコードの部分

以下のコードはjestのテストをしていて、モックされた関数を呼んで1回目の関数呼び出しの場合は400をリターンさせて、2回目の呼び出しのときは200をリターンさせる・・・
という感じのことをしています。

で、テストケースが一つだけならこれでうまくいくが、2回以上同じように以下のコードの塊をコピーして書くとexpectの結果が意図しないものになる。

ちなみに、監視している関数に使われた引数を見るには「mockFn.mock.calls」を使うが、この引数も、関数が呼ばれるたびに引数が積み重なっていく感じになってしまう(例えば一回目の引数が配列の[1,2]だとして次の呼び出しの引数が[3]だとしたら、2回目のテストでmockFn.mock.callsして引数を見ると「1,2,3」になって蓄積されてしまう)

以下の塊を、テストケースの数だけ複数書くことを想定

anime-suko.ts
const testCase1 = test('正常系1:hogehoge', async () => {

  const testFailedExpectResponse = {
    statusCode: 200,
  }

  //ここでモックして、レスポンス内容を指定
  jest
    .spyOn(hogeLambdaModule, 'hogeLambda')
    .mockResolvedValueOnce(Promise.resolve({ statusCode: 400 }))
    .mockResolvedValueOnce(Promise.resolve({ statusCode: 200 }))
    .mockResolvedValueOnce(Promise.resolve({ statusCode: 200 }))
    .mockResolvedValueOnce(Promise.resolve({ statusCode: 200 }))

  //Exercise
  const actual = await getPrivateMethodsInTestModule.lambdaFunction()

  //verify
  //ステータスコードが400で返ってくること
  expect(actual).toStrictEqual(testFailedExpectResponse)
})


解決方法

原因は、spyOnによるモック化を何回も繰り返してしまっていたから。
このままだと同じ設定を繰り返す感じになって不具合の原因になる。
気持ちとしては、テストのたびにモックをクリーンな状態にするのが一般的。
なので、 jestのrestoreAllMocks()を使って元の状態に復元する必要がある。

restoreAllMocks()の詳細については以下にドキュメントがあります
https://jestjs.io/docs/ja/jest-object

●以下のように、テストを4つのフェーズで考えるやつで、そのうちのteardown(後処理)にあたることをします
以下の処理を、全てのtest()の中に追記したら解決しました

anime-suko.ts
  //teardown
  jest.restoreAllMocks()

まとめ