Next.js の API Routes に書かれた実装のテスト

Next.js の API Routes に書かれた実装をテストしたいときを考えたい(jest)。

まずは簡単な api を作ってみる。クエリパラメータ animal=dog をつけて/api/check?animal=dog としてアクセスすると /dog にリダイレクトし、逆にクエリパラメータ animal=dog 無しでアクセスすると 400 が返ってくる API を作ってみる。

import { NextApiRequest, NextApiResponse } from "next";

// pages/api/check.api.ts
export default async (
  req: NextApiRequest,
  res: NextApiResponse
): Promise<void> => {
  if (req.query.animal !== "dog") {
    res.statusCode = 400;
    res.end();
    return;
  }

  res.redirect(
    302,
    "/dog",
  );
};

これに対するテストは以下のようにかけそう。

import httpMocks from "node-mocks-http";
import handler from "pages/api/check.api.ts";

describe("/api/check", () => {
  test("400", async () => {
    const mockReq = httpMocks.createRequest<NextApiRequest>({
      query: {
        animal: "cat",
      },
    });
    const mockRes = httpMocks.createResponse<NextApiResponse>();
  
    await handler(mockReq, mockRes);
    expect(mockRes.statusCode).toEqual(400);
  });

  test("302", async () => {
    const mockReq = httpMocks.createRequest<NextApiRequest>({
      query: {
        animal: "dog",
      },
    });
    const mockRes = httpMocks.createResponse<NextApiResponse>();
  
    await handler(mockReq, mockRes);
    expect(mockRes.statusCode).toEqual(302);
    expect(mockRes._getRedirectUrl()).toEqual(
      "/dog"
    );
  });
}

今回の API Routes は関数無名関数で export default しているので適当な名前を付けて import する。それをそのまま呼んで必要としている変数 NextApiRequestNextApiResponse を渡してあげると良い。この2つを自力で作るよりも node-mocks-http を使ったほうが一瞬でできて楽そうなので使っている。

www.npmjs.com

mockRes に処理後の状態が入っているので、mockRes のプロパティをチェックしてちゃんと出来ているか確認する感じです。