JavaScript
jest

Jestで非同期関数が例外を投げることをテストする。

背景

バイトで、Async関数が例外を投げてくれること、そしてその例外がどの例外であるかをテストする必要が出てきました。そのときのメモを残しておこうと思います。

やってみよう

expectに関数を渡して、toThrowしてやると非同期でない関数が例外を投げるかどうかをテストできます。しかし、この場合、expectにAsync関数を渡しても期待どおりのテストを行うことはできません。

test('throws on octopus', () => {
  expect(() => {
    drinkFlavor('octopus');
  }).toThrow();
});

非同期処理が失敗したときに追加でアサーションを行うためには、rejectsを使います。この場合、Promiseが成功したときはアサーションが失敗します。

次のようなdrinkFlavorがあったとします。

async function drinkFlavor(flavor) {
  if (flavor == 'octopus') {
    throw new DisgustingFlavorError('yuck, octopus flavor');
  }
  // Do some other stuff
}

この関数に引数'octopus'を渡したときにDisgustingFlavorErrorをThrowすることをテストします。

test('rejects to octopus', async () => {
  const drinkFlavorPromise = drinkFlavor('octopus')
  await expect(drinkFlavorPromise).rejects.toThrow();
});

そして、toThrowに引数を与えることによって、そのThrowされた例外が'octopus'を含んで投げられたかどうかをテストします。この引数には正規表現を与えることも可能です。

test('rejects to octopus', async () => {
  const drinkFlavorPromise = drinkFlavor('octopus')
  await expect(drinkFlavorPromise).rejects.toThrow('octopus');
});

そして、toThrowErrorを使うことで、その投げられたErrorがDisgustingFlavorErrorであるかどうかをテストできます。

test('rejects to octopus', async () => {
  const drinkFlavorPromise = drinkFlavor('octopus')
  await expect(drinkFlavorPromise).rejects.toThrowError(DisgustingFlavorError);
});

感想

そこそこよくあるパターンではあると思うのですが、今まで出くわさなかったので、これを機に知れて嬉しいですね。