JestでNode.jsのfetchをテストしたい

背景

内部でfetchを呼んでいる関数をテストしたいです。 Nodeのv18以降ではnode-fetchなしでfetchが使えるようになりましたが、node-fetchを使っているサンプルが多く組み込みのfetchを使っているサンプルが少ないので調べました。

結論

node:testモジュールのmock.methodを使うか、Jestのjest.spyOnを使います。

mock.methodの場合

import { mock } from "node:test"

// テスト対象メソッド。成功すると"Hello"が返ってくる。
async function fetchData() {
    const res = await fetch("https://example.com/");
    if (!res.ok) {
        return "NG";
    }

    return res.text();
}

it("fetchに成功するとHelloを返す", async () => {
    mock.method(global, "fetch", () => Promise.resolve(new Response("Hello"));
    const result = await fetchData();
    expect(result).toBe("Hello");
    mock.reset();
});

jest.spyOnの場合

// テスト部分のみ
it("fetchに成功するとHelloを返す", async () => {
    const spy = jest.spyOn(global, "fetch");
    spy.mockImplementation(() => Promise.resolve(new Response("Hello")));

    const result = await fetchData();
    expect(result).toBe("Hello");
    spy.mockRestore();
});