针对未处理的超测请求的 MSW 日志记录警告

MSW logging warnings for unhandled Supertest requests

在我使用 Supertest 和 MSW 进行的测试中,我注意到,虽然它们仍然成功通过,但 MSW 已经开始对 Supertest 发出的请求显示警告。例如(请参阅 post 末尾要复制的文件):

$ npm t

> msw-example@1.0.0 测试
> 开玩笑

 通过 ./app.test.js
  密码 API
    ✓ 暴露了一些单词(76 毫秒)

  console.warn
    [MSW] 警告:捕获了没有匹配请求处理程序的请求:

      • 获取 http://127.0.0.1:55984/api

    如果您仍然希望拦截这个未处理的请求,请为它创建一个请求处理程序。
    阅读更多:<a href="https://mswjs.io/docs/getting-started/mocks" rel="nofollow noreferrer">https://mswjs.io/docs/getting-started/mocks</a>

      在 onUnhandledRequest (node_modules/msw/node/lib/index.js:7599:21)
      在 node_modules/msw/node/lib/index.js:7630:13
      在履行 (node_modules/msw/node/lib/index.js:50:58)

测试套件:1 个通过,共 1 个
测试:1 次通过,共 1 次
快照:共 0 个
时间:1.005 秒
运行 所有测试套件。

请求 GET http://127.0.0.1:55984/apiSupertest 向应用程序发出的请求,这是测试的重点,而不是 MSW 需要处理的请求。我第一次编写测试时也没有显示这些警告。

链接页面显示了如何创建处理程序,但我不希望 MSW 处理这些请求。为什么会发生这种情况,我如何才能阻止它显示 "/api" 调用的警告?


package.json:

{
  "name": "msw-example",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "jest"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "dependencies": {
    "axios": "^0.21.1",
    "express": "^4.17.1"
  },
  "devDependencies": {
    "jest": "^27.0.4",
    "msw": "^0.29.0",
    "supertest": "^6.1.3"
  }
}

app.js:

const axios = require("axios");
const express = require("express");

const app = express();

app.get("/api", (_, res) => {
  axios.get("https://api.pwnedpasswords.com/range/ABC12")
    .then(() => res.json({ words: 3 }))
    .catch((err) => res.sendStatus(500));
});

module.exports = app;

app.test.js:

const { rest } = require("msw");
const { setupServer } = require("msw/node");
const request = require("supertest");

const app = require("./app");

const server = setupServer(
  rest.get("https://api.pwnedpasswords.com/range/:range", (req, res, ctx) => {
    return res(ctx.status(200), ctx.text(""));
  }),
);

describe("password API", () => {
  beforeAll(() => server.listen());

  beforeEach(() => server.resetHandlers());

  afterAll(() => server.close());

  it("exposes a number of words", () => {
    return request(app).get("/api").expect(200).then((res) => {
      expect(res.body.words).toBe(3);
    });
  });
});

此功能是在 MSW v0.20.0, but in v0.29.0 the default setting for unhandled requests changed from "bypass" to "warn", hence the warnings suddenly appearing in the console. You can reset it to "bypass" as shown in the docs for setupWorker#start or setupServer#listen 中引入的,在我的例子中:

beforeAll(() => server.listen({ onUnhandledRequest: "bypass" }));

但是,这可能意味着您 应该 处理的请求缺少警告,因此另一种选择是传递接收请求对象的函数。这可以例如记录警告或抛出错误(这将导致测试失败)。就我而言,由于我所有的超测请求都是针对 /api 个端点,因此看起来像:

beforeAll(() => server.listen({ 
  onUnhandledRequest: ({ method, url }) => {
    if (!url.pathname.startsWith("/api")) {
      throw new Error(`Unhandled ${method} request to ${url}`);
    }
  },
}));

根据 kettanaito in the comments, I looked into whether you could identify Supertest calls by their headers. Unfortunately it seems like Supertest no longer 的建议设置默认值 User-Agent,因此您必须逐项测试:

describe("password API", () => {
  beforeAll(() => server.listen({ 
    onUnhandledRequest: ({ headers, method, url }) => {
      if (headers.get("User-Agent") !== "supertest") {
        throw new Error(`Unhandled ${method} request to ${url}`);
      }
    },
  }));

  beforeEach(() => server.resetHandlers());

  afterAll(() => server.close());

  it("exposes a number of words", () => {
    return request(app)
      .get("/api")
      .set("User-Agent", "supertest")
      .expect(200)
      .then((res) => {
        expect(res.body.words).toBe(3);
      });
  });
});

v0.38.0 开始,您可以使用 second 参数到 onUnhandledRequest,通常命名为 print,以在某些情况下将控制权交还给 MSW你不想处理,例如:

beforeAll(() => server.listen({ 
  onUnhandledRequest: ({ headers }, print) => {
    if (headers.get("User-Agent") === "supertest") {
      return;
    }
    print.error();
  },
}));