テスト中、fetch関数の動作を一時的に書き替えて、任意の値を返すように変更する方法について解説します。
fetchをstubする方法
Denoのテストで一時的に関数の動作を書き換える時は、標準ライブラリのtesting/mockモジュールを使用します。
このモジュールにはstub以外にもspyやらFakeTimeやら色々入っているのですが、今回はstubのみ取り上げます。
stub関数の使い方
以下のように書きます。
// deno test
import { assertEquals } from "https://deno.land/std@0.152.0/testing/asserts.ts";
import {
assertSpyCallArgs,
assertSpyCalls,
stub,
} from "https://deno.land/std@0.152.0/testing/mock.ts";
Deno.test({
name: "fetch test",
async fn() {
const mockFetchText = "__MOCK_FETCH__";
const fetchStub = stub(
globalThis,
"fetch",
() => Promise.resolve(new Response(mockFetchText)),
);
try {
// テストコード
const res = await fetch("foo.com");
// fetchの結果が書き変わっていることを確認
assertEquals(await res.text(), mockFetchText);
// fetchの0回目の呼び出しの引数を確認
assertSpyCallArgs(fetchStub, 0, ["foo.com"]);
// fetchの呼び出し回数が1回であることを確認
assertSpyCalls(fetchStub, 1);
} finally {
// 必ずrestoreを呼んで、fetchのstubを解除する
fetchStub.restore();
}
},
});
ポイントはstub
関数を呼んでいるところです。
この関数が以下のように呼ばれると以降はfetch
の実装がモックしたものに切り替わります。
// globalThis の fetch プロパティを 3番目の引数に渡した関数で置きかえる
const fetchStub = stub(
globalThis,
"fetch",
() => Promise.resolve(new Response(mockFetchText)),
);
テストの最後には、必ずstubを解除しましょう。stub.restore()
関数を利用します。
try {
// ここにテストコード
} finally {
fetchStub.restore();
}
finally
節の中で呼ぶことで、テストが途中で失敗した場合にもstubが解除されるようにします。
assertSpyCallArgs / assertSpyCalls
テスト用のユーティリティとして、assertSpyCallArgs
とassertSpyCalls
が用意されています。
これらの関数を使うと、スタブがどのような引数で呼び出されたのかや、何回呼び出されたのかが分かります。
// fetchの0回目の呼び出しの引数を確認
assertSpyCallArgs(fetchStub, 0, ["foo.com"]);
// fetchの呼び出し回数が1回であることを確認
assertSpyCalls(fetchStub, 1);
これらの関数は、結果が期待通りでなかった時にthrow
し、テストを失敗させます。
実はこれ以外にもテストに便利なユーティリティー関数がいくつか存在しているので、詳しくは↓を参照してください!
まとめ
-
fetch
関数をスタブするには、testing/mock
モジュールを使用する。 - スタブした関数がどのように呼び出されたかを知るには、
assertSpyCallArgs
やassertSpyCalls
を使う。