在Cypress测试文件中启动本地服务器遇Webpack编译错误求助
问题分析与解决方案
核心问题
你遇到的Webpack编译错误,本质是错误地在浏览器环境的测试代码中引入了Node.js专属的服务器依赖:
- Cypress测试代码运行在浏览器环境,Webpack会尝试打包所有引入的模块,但
mysql2等Node模块使用了Webpack默认配置不支持的ES私有类字段语法(static #constructing),导致编译失败。 - 你的服务器文件导出逻辑错误:
module.exports = test();直接执行了启动函数,导出的是app.listen返回的Server实例,而非可调用的函数,测试文件里的xxxx.tes()本身就是无效调用。
解决方案步骤
1. 重构服务器文件,支持启动/关闭控制
修改index.js,导出可控制的启动、停止函数和app实例,方便后续在Node环境中管理:
const express = require("express"); const app = express(); const port = 3000; const programmingLanguagesRouter = require("./routes/programmingLanguages"); app.use(express.json()); app.use(express.urlencoded({ extended: true })); app.get("/", (req, res) => { res.json({ message: "ok" }); }); app.use("/programming-languages", programmingLanguagesRouter); /* Error handler middleware */ app.use((err, req, res, next) => { const statusCode = err.statusCode || 500; console.error(err.message, err.stack); res.status(statusCode).json({ message: err.message }); return; }); let server; // 启动服务器,返回Promise便于异步控制 function startServer() { return new Promise((resolve) => { server = app.listen(port, () => { console.log(`Example app listening at http://localhost:${port}`); resolve(server); }); }); } // 关闭服务器,返回Promise function stopServer() { return new Promise((resolve, reject) => { if (server) { server.close((err) => err ? reject(err) : resolve()); } else { resolve(); } }); } module.exports = { startServer, stopServer, app };
2. 在Node环境启动/关闭服务器(避免Webpack编译)
Cypress允许通过配置文件或cy.task在Node环境执行代码,不会经过浏览器端的Webpack编译,这才是启动测试服务器的正确方式。
方案一:全局钩子控制(所有测试共用服务器)
修改cypress.config.js(旧版Cypress用cypress/plugins/index.js),在测试全局生命周期中启动/关闭服务器:
const { defineConfig } = require("cypress"); // 替换为你的服务器文件实际路径 const { startServer, stopServer } = require("../server/index.js"); module.exports = defineConfig({ e2e: { setupNodeEvents(on, config) { let server; // 所有测试启动前启动服务器 on("before:run", async () => { server = await startServer(); }); // 所有测试结束后关闭服务器 on("after:run", async () => { await stopServer(); }); }, }, });
方案二:单个测试文件控制(灵活启停)
如果需要在单个测试文件中控制服务器,先在cypress.config.js注册任务:
const { defineConfig } = require("cypress"); const { startServer, stopServer } = require("../server/index.js"); module.exports = defineConfig({ e2e: { setupNodeEvents(on, config) { let server; on("task", { startServer: async () => { if (!server) server = await startServer(); return "Server started"; }, stopServer: async () => { await stopServer(); return "Server stopped"; }, }); }, }, });
然后修改测试文件test.spec.js:
describe("Calling the endpoint", () => { // 测试前启动服务器 before(() => { cy.task("startServer"); }); // 测试后关闭服务器 after(() => { cy.task("stopServer"); }); context("Test", () => { it("should return 200 for programming-languages endpoint", () => { cy.request({ method: 'GET', headers: { 'Content-Type': 'application/json', 'accept': 'application/json' }, url: 'http://localhost:3000/programming-languages' }).then((res) => { expect(res.status).to.equal(200); }); }); }); });
内容的提问来源于stack exchange,提问作者EFPM_S
相关产品推荐
相关产品推荐

