使用Cypress进行Angular-NestJS全栈应用E2E测试时遭遇net::ERR_EMPTY_RESPONSE:真实服务端请求无法抵达后端
你的问题核心在于:Cypress运行的Angular应用的浏览器环境,和cy.request()的Node.js环境对后端请求的处理逻辑不一样——cy.request()默认跳过了浏览器的安全限制(比如证书验证、跨域检查),但Angular应用在浏览器里发起的请求会受到这些限制,同时可能还有配置上的不匹配。
下面是不用存根(stub)就能让真实请求正常工作的关键步骤:
1. 检查Angular的API地址配置
首先确认Angular环境文件(比如src/environments/environment.ts)里的API基础地址是否正确:
- 如果使用绝对路径,要确保是
https://localhost:443(注意协议是HTTPS,因为443是默认HTTPS端口); - 如果使用相对路径(比如
'/load'),需要配合Cypress的代理配置来转发请求到后端,避免跨域问题。
2. 处理HTTPS证书问题(如果后端用自签名证书)
如果你的NestJS后端用的是自签名HTTPS证书,浏览器会拒绝信任它,导致Angular请求失败,但cy.request()默认跳过了证书验证。解决方法有两种:
- 推荐方案:把自签名证书添加到你的系统信任存储中,这样浏览器会认可该证书;
- 临时方案:在
cypress.config.js中关闭Chrome的安全检查(注意这会禁用部分浏览器安全机制,仅用于测试环境):
// cypress.config.js const { defineConfig } = require('cypress'); module.exports = defineConfig({ e2e: { baseUrl: 'http://localhost:4200', // 你的Angular应用运行地址 chromeWebSecurity: false, }, });
3. 配置Cypress代理转发请求
如果Angular使用相对路径请求API(比如'/load'),可以通过Cypress的代理功能把这些请求转发到后端,避免跨域和地址不匹配问题:
// cypress.config.js const { defineConfig } = require('cypress'); module.exports = defineConfig({ e2e: { baseUrl: 'http://localhost:4200', setupNodeEvents(on, config) { // 配置代理,将/load请求转发到后端 config.proxy = { '/load': { target: 'https://localhost:443', changeOrigin: true, secure: false // 若后端是自签名证书,需要开启这个 } }; return config; }, }, });
这样当Angular发起/load请求时,Cypress会自动将其转发到https://localhost:443/load。
4. 配置NestJS的CORS策略
确保NestJS后端允许Cypress运行的Angular应用的来源访问API。在NestJS的main.ts中添加CORS配置:
async function bootstrap() { const app = await NestFactory.create(AppModule); // 允许Angular应用的来源访问,credentials设为true以支持会话/cookie app.enableCors({ origin: 'http://localhost:4200', credentials: true }); await app.listen(443); } bootstrap();
如果需要支持多个测试环境的来源,可以用数组(比如['http://localhost:4200', 'http://localhost:3000'])或者正则表达式。
5. 验证请求的实际状态
在Cypress测试运行时,点击测试界面的Open DevTools按钮,查看Network标签:
- 检查Angular发起的请求的实际URL是否正确;
- 查看请求的状态码(比如403、500)或错误信息(比如跨域错误、证书错误),这能帮你快速定位剩余的配置问题。
通过以上步骤,你的Angular应用应该就能在Cypress中正常发起真实的后端请求了,不需要手动存根响应。
内容的提问来源于stack exchange,提问作者Sascha Geier

