SuperTest と msw 併用時に warning log を抑止する

Yosuke Kurami
5 min readSep 5, 2022

--

BFF などの「Upstream Service に HTTP を叩いてその response を加工しつつ、自分自身の response を返却する」類の Node.js API サーバーを考える。

Service としてのスタックは以下のようなイメージ:

  • API Aggregation Endpoint: Express
  • Upstream HTTP Call: Fetch API (cross-fetch, undici, etc…)

この Service に対して、API Integration Test を記述する目的で以下を導入したとする。

  • jest
  • SuperTest
  • msw/node

すなわち、API Aggregation Endpoint の実装が下記のようになっていて、

import express from "express";export const app = express();app.get("/api/foo", (req, res) => {
fetch("http://upstream.service.local/api/hoge")
.then(result => {
if (!result.ok) return res.status(400).end();
return result.json() as { value: number };
})
.then(data => {
return res
.json({ result: data.value * 2 })
.status(200)
.end();
});
});

これに対する Integration Test が下記のようになっているイメージ。

import request from "supertest";
import { rest } from "msw";
import { setupServer } from "msw/node";
import { app } from "./app";describe("GET /api/foo", () => {
const upstreamServices = setupServer(
...[
rest.get("http://upstream.service.local/api/hoge", (req, res, ctx) =>
res(ctx.json({ value: 100 }), ctx(200))
)
]
);
beforeAll(() => upstreamServices.listen());
afterEach(() => upstreamServices.resetHandlers());
afterAll(() => upstreamServices.close());
it("should respond 200", async () => {
const response = await new Promise<request.Response>((resolve, reject) =>
request
.get("/api/foo")
.expect(200)
.end((err, response) => (err ? reject(err) : resolve(response)))
);
expect(response.body.result).toBe(200);
});
});

上記のパターンの integration test 記述を初めてやったのだけど、msw と SuperTest を併用していると、msw 側が SuperTest の対象の request について「それ、mock handler すり抜けるけど大丈夫?」的な Warning を jest に履いてきて地味に鬱陶しい。

console.warn
[MSW] Warning: captured a request without a matching request handler:

• POST http://127.0.0.1:36489/api/foo/

If you still wish to intercept this unhandled request, please create a request handler for it.
Read more: https://mswjs.io/docs/getting-started/mocks

listen するときに onUnhandledRequest というオプションが用意されていて、ここを引っ掛けると柔軟にカバーできる。

大概の場合、supertest に対する Subject Endpoint だけを Warning から除外すれば十分なはずなので、以下のようにすると良さそう。

upstreamServices.listen({
onUnhandledRequest: (mockedReq, print) => {
if (mockedReq.url.pathname === "/api/foo") return null;
print.warning();
}
});

--

--

Yosuke Kurami

Front-end web developer. TypeScript, Angular and Vim, weapon of choice.