🐧

Vitestでnode-fetchのfetchをmockする

2022/04/17に公開

やりたいこと

フロントエンドJavascriptのfetchをVitestでmockしたいという記事を書きました。
https://zenn.dev/akira_kashihara/articles/650c558ae02db0
これを実現するために、いろいろと調べた過程で、副産物として、Vitestでnode-fetchのfetchをmockする方法を実装したので、まとめておきます。

環境の導入

まだ、Vitest[1]はメジャーなツールではないので、一応、導入方法についても書いておきます。

npm i -D vitest vi-fetch node-fetch

テスト対象の関数

記事用に、かなり簡素化したテスト対象の関数を作ります。この関数は、https://hogehoge.hogehoge.hogehoge というサイトをGETして、そのレスポンスのjsonにあるcountの値を返すだけです。

getCountNode.js
import fetch from "node-fetch";

export const getCountNode = async () => {
  const response = await fetch("https://hogehoge.hogehoge.hogehoge"); // GETする
  const countJson = await response.json(); // Responseのbodyをjsonで得る
  return countJson.count; // 得られたjsonのcountの値を返す
};

テストを書く

テストを書きます。VitestはJestと多くの部分で互換性があります。Jestにはnode-fetchをmockする方法が公式で公開されていて[3]、これを参考に作れば良いのですが、jest.requireActualヘルパーはVitestにはありません。そのため、stack overflowでE. Colemanらが示している方法[1:1]を参考に、実装しています。

nodeFetch.test.js
import { describe, it, expect, vi } from "vitest";
import fetch from "node-fetch";
import { getCountNode } from "./getCountNode";

describe("sample", () => {
  it("hello", async () => {
    vi.mock("node-fetch");
    fetch.mockReturnValue(
      Promise.resolve({ json: () => Promise.resolve({ count: 33 }) })
    );
    const result = await getCountNode();
    expect(result).toBe(33);
  });
});

テストを実行してみる

実行すると、以下のように通ります。テスト結果が2 passedになっているのはフロントエンドJavascriptのfetchを同時にテスト[2:1] しているからです(手抜きですみません)。
passed

わざと通らないようにする

わざとテストが通らないようにテストコードを変更してみます。

nodeFetch.test.js
import { describe, it, expect, vi } from "vitest";
import fetch from "node-fetch";
import { getCountNode } from "./getCountNode";

describe("sample", () => {
  it("hello", async () => {
    vi.mock("node-fetch");
    fetch.mockReturnValue(
      Promise.resolve({ json: () => Promise.resolve({ count: 33 }) })
    );
    const result = await getCountNode();
    expect(result).toBe(31);
  });
});

結果はこちら

さいごに

この記事は、以下の記事のおまけです。フロントエンドJavascriptのfetchをモックしたい人はぜひ、一読ください。
https://zenn.dev/akira_kashihara/articles/650c558ae02db0

脚注
  1. asked by BobMorane, answered by E. Coleman / Jest - TypeError: response.json is not a function https://stackoverflow.com/questions/58599735/jest-typeerror-response-json-is-not-a-function (2022-04-17閲覧) ↩︎ ↩︎

  2. Akira Kashihara / VitestでフロントエンドJavascriptのfetchをmockする https://zenn.dev/akira_kashihara/articles/650c558ae02db0 (2022-04-17閲覧) ↩︎ ↩︎

  3. Jest / モジュールモックのバイパス https://jestjs.io/ja/docs/next/bypassing-module-mocks (2022-04-17閲覧) ↩︎

Discussion