少しつまづいたので備忘録残します。
環境 Next.js 14.1 , App Route
APIルートの単体テスト
次のようなAPIルートがあります。
import { NextResponse } from "next/server";
export async function GET(request: Request) {
return NextResponse.json({
message: `Hello`,
});
}
GETに対するjestを使った単体テストは次のように書けます。
import { GET } from "./route";
describe("GET /api/hello", () => {
it("returns a message", async () => {
const url = new URL("http://localhost/api/hello");
const response = await GET(new Request(url));
expect(response.status).toBe(200);
expect(response.headers.get("content-type")).toBe("application/json");
const body = await response.json();
expect(body).toEqual({ message: "Hello" });
});
});
このテストは通るはずですが、今回 ReferenceError: Request is not defined
というエラーが出てテストが実行できない問題に遭遇しました。
原因 テスト環境がjsdomだった
jestのtestEnvironmentオプションでは、テストが実行される環境を指定することができます。
デフォルトはjsdomで、ブラウザ環境をエミュレートします。Reactコンポーネントやその他のブラウザ依存のコードをテストする場合に設定します。
testEnvironment: "jsdom",
一方、nodeを指定するとNode.jsの環境でテストが実行されます。サーバーサイドのコードはこちらを指定する必要があります。
testEnvironment: "node",
RequestオブジェクトやResponseオブジェクトはサーバーサイドでのみ利用できるので、jsdom環境でのテストでは参照できません。
解決方法としては、jest.config.tsでtestEnvironmentをnodeに変更するか、ファイルの先頭で環境を指定します。
/**
* @jest-environment node
*/
import { GET } from "./route";
describe("GET /api/hello", () => {
it("returns a message", async () => {
const url = new URL("http://localhost/api/hello");
const response = await GET(new Request(url));
expect(response.status).toBe(200);
expect(response.headers.get("content-type")).toBe("application/json");
const body = await response.json();
expect(body).toEqual({ message: "Hello" });
});
});