我在测试 Express 端点时遇到 Supertest 问题,它会随机失败,通常会出现
AxiosError: Request failed with status code 404
错误,没有有用的堆栈跟踪。
该错误每次都发生在随机文件上。如果我直接运行该文件的测试,它们都会很好地通过,任何测试实际上都没有问题,直接运行时它们都会通过。
问题出在运行全套测试时(大约 40 个文件中的大约 280 个测试)。总是会出现至少一个,有时甚至更多相同的错误:
● Test suite failed to run
AxiosError: Request failed with status code 404
at settle (node_modules/axios/lib/core/settle.js:19:12)
at IncomingMessage.handleStreamEnd (node_modules/axios/lib/adapters/http.js:599:11)
at Axios.request (node_modules/axios/lib/core/Axios.js:45:41)
该错误似乎与文件中的测试完全无关。有时,失败的测试文件是纯单元测试,不执行任何类型的 HTTP 请求,甚至不使用 Axios 导入任何内容,但它会抛出相同的 Axios 错误。
我通过 Supertest 发现了这个问题。我重构了所有测试以使用这个新的启动和关闭程序,但它什么也没做。
另一个可能有用的信息是,错误总是发生在整个套件运行的一半到 3/4 左右。它永远不会立即发生,并且总是在不同的测试文件上。
我如何才能提供更多信息来调试它?不可能知道它发生在哪里,因为它的失败测试实际上与错误无关。我什至无法展示失败测试的示例,因为它们在单独运行时都通过了。
我所有的测试都遵循这个模式:
const request = supertest(app);
describe("functionName", () => {
it("should perform x", async () => {
const res = await request.get("/v1/asset");
const { result } = res.body;
expect(res.status).toEqual(200);
// etc etc
});
});
app
的示例:
import express from "express";
const app = express();
app.get("/routes", (req, res) => {
res.json({});
});
export default app;
运行:Node 20.16、Yarn 4.4.0、Jest 29.7.0、Supertest 6.3.4
如果其他人遇到类似的问题,请在这里回答我自己的问题,因为这是一个很难解决的问题。
如上所述,该错误是 Axios 抛出的关于某些 404 响应的通用异常。 它在随机测试中看似随机的时间发生,甚至没有执行 Axios 请求。
堆栈跟踪没有帮助,错误没有提供任何有用的信息(我们的应用程序中有数百个 axios 调用,是哪一个?)。
我能够通过在
jest.config.js
中配置设置JS文件来调试错误源
setupFilesAfterEnv: ["./tests/setupJest.ts"]
此文件在所有测试之前运行。
在这个文件中,我配置了一个 Axios 拦截器来拦截 Axios 响应和错误响应,以便您可以注销有关请求、URL、方法等的信息。
axios.interceptors.response.use(
(response) => {
// Any status code that lie within the range of 2xx cause this function to trigger
// Do something with response data
return response;
},
async (error) => {
// Any status codes that falls outside the range of 2xx cause this function to trigger
// Do something with response error
console.log("AXIOS DEBUG", error.request.method, error.request.path, error.response.status, error.stack);
return Promise.reject(error);
}
);
现在,当我在控制台中运行测试套件时,在这个神秘的 404 错误所在的位置,我可以看到请求路径和方法已注销,在我的例子中,这是对外部端点的 DELETE 请求,基本上是删除操作。
这显着缩小了潜在的罪魁祸首代码的范围。
我审查了执行此操作的所有测试,果然我发现了一个未
await
ed 的 Axios 删除请求,因此它正在运行并导致请求失败,但此时另一个测试已开始。
向这一行添加一个等待,解决了问题,但如果没有这一点信息,我永远不会在我们超过 100 万行的代码库中找到这一行代码。
希望能帮助别人摆脱沮丧的日子。