selmertsxの素振り日記

ひたすら日々の素振り内容を書き続けるだけの日記

TypeScriptのnode-fetchをテストの際にmockする

モチベーション

  • TypeScript で node-fetch のライブラリを使ってテストするのに少し手間取った
  • 他にもハマる人がいるかも知れないので、ここに記事として残しておく

テストしたい内容

  • Soracom Arcを利用して unified endpointにテストデータを送信したい
  • テストデータの送信では node-fetch というライブラリを利用する
  • node-fetch を利用して所望のパラメータが送信されていることを確認したい

結論: 実装内容

実装は下記の通り。 重要な部分は ts-jest のtest-helpersを利用しているところ。 ts-jestが必要な理由は後述する

// src/publisher.ts
import fetch from "node-fetch";
export const UNIFIED_ENDPOINT_URL = "http://unified.soracom.io";

export const main = async () => {
  const body = { /* なんらかのデータ*/ };
  await fetch(UNIFIED_ENDPOINT_URL, {
    method: "POST",
    body: JSON.stringify(body),
  });
};

(async () => await main())();
// tests/publisher.test.ts
import fetch, { Response } from "node-fetch";

// SEE: https://kulshekhar.github.io/ts-jest/docs/guides/test-helpers
import { mocked } from "ts-jest/utils";
import { main, UNIFIED_ENDPOINT_URL } from "../src/publisher";
jest.mock("node-fetch");

describe("Publisher", () => {
  test("main", async () => {
    mocked(fetch).mockReturnValue(
      Promise.resolve(new Response("ok", { status: 200 }))
    );
    const expectResponse = { /* 何らかのデータ */ };
    await main();
    expect(fetch).toBeCalledWith(UNIFIED_ENDPOINT_URL, {
      body: JSON.stringify(expectResponse),
      method: "POST",
    });
  });
});

Jest公式ドキュメントの手法

Jest公式では node-fetch のようなライブラリのテスト方法は下記のように指示されている。 だが、これは TypeScript ではコンパイルエラーとなりテストができない。 そのため、ts-jestを導入して対処する必要があった。

jest.mock('node-fetch');

import fetch, {Response} from 'node-fetch';
import {createUser} from './createUser';

test('createUser calls fetch with the right args and returns the user id', async () => {
  fetch.mockReturnValue(Promise.resolve(new Response('4')));

  const userId = await createUser();

  expect(fetch).toHaveBeenCalledTimes(1);
  expect(fetch).toHaveBeenCalledWith('http://website.com/users', {
    method: 'POST',
  });
  expect(userId).toBe('4');
});

f:id:selmertsx:20210811105327p:plain