使用Protractor运行Angular 4应用E2E测试时调用API失败
解决Angular 4 E2E测试时的CORS跨域问题
我之前也踩过这个坑!Angular的E2E测试默认会随机分配端口(就是你碰到的49155这类),而你的Express后端只把http://localhost:4200加入了CORS白名单,自然就触发跨域拦截了。给你三个实用的解决办法,按需选择:
办法一:强制E2E测试使用固定端口4200
直接让E2E测试复用开发环境的端口,这样CORS配置不用改就能正常工作。Angular 4里可以通过命令行参数指定端口:
ng e2e --port 4200
如果想一劳永逸,也可以修改protractor.conf.js里的配置,把baseUrl设为http://localhost:4200。不过要注意,如果你同时开着ng serve占用4200端口,测试会启动失败,得先关掉开发服务。
办法二:动态配置Express的CORS允许规则
既然E2E端口是随机的,不如让后端自动放行所有本地localhost的端口。把你的CORS配置改成函数判断的形式:
app.use(cors({ origin: function(origin, callback) { // 允许无origin请求(比如Postman)和所有localhost端口的请求 if (!origin || /^http:\/\/localhost:\d+$/.test(origin)) { callback(null, true); } else { callback(new Error('Not allowed by CORS')); } }, credentials: true }));
这个方案最灵活,不管是开发的4200还是测试的随机端口,只要是本地请求都能通过,而且不影响生产环境的安全(生产环境你可以单独配置正式域名)。
办法三:在E2E测试中配置API代理
把测试里的API请求代理到Express服务器,这样浏览器请求的是测试服务器的端口,不会有跨域问题。修改protractor.conf.js,在onPrepare钩子中设置请求拦截:
exports.config = { // 其他配置... onPrepare: function() { // 拦截/api开头的请求,转发到Express服务器 browser.addMockModule('apiProxy', function() { angular.module('apiProxy', []).config(['$httpProvider', function($httpProvider) { $httpProvider.interceptors.push(function() { return { request: function(config) { if (config.url.startsWith('/api')) { config.url = 'http://localhost:3000' + config.url; } return config; } }; }); }]); }); } };
这个方案适合希望测试环境更贴近生产代理配置的场景,但需要额外写拦截逻辑,稍微麻烦一点。
内容的提问来源于stack exchange,提问作者gh0st
相关产品推荐
相关产品推荐

