使用JEST运行Express测试时出现Cross origin http://localhost forbidden错误
报错原因
你遇到的跨域报错和Express服务端的CORS配置无关,本质是Jest测试环境的问题:
- Jest部分旧版本或前端项目默认配置会使用
jsdom模拟浏览器环境运行测试,axios在浏览器环境下会走XMLHttpRequest发起请求,受同源策略限制,你本地测试的origin是http://localhost,调用谷歌地图API属于跨域请求,直接被同源策略拦截。 - 你测试的是后端服务逻辑,不需要模拟浏览器环境,也不需要真实发起第三方API请求,所以有多种方案可以解决问题。
解决方案
方案1:修改Jest测试环境为Node(最适配你的场景)
你测试的是Express后端逻辑,直接把测试环境切为Node即可规避浏览器同源策略限制:
在项目的jest.config.js中添加配置:
module.exports = { // 其他现有配置 testEnvironment: 'node' }
如果你的Jest配置写在package.json里,对应添加字段即可:
{ "jest": { "testEnvironment": "node" } }
方案2:强制指定axios使用Node端请求适配器
如果你确实需要保留jsdom测试环境,可以单独给axios指定Node端的http适配器,绕过浏览器XHR的同源策略校验:
可以在测试文件顶部添加配置:
const axios = require('axios'); axios.defaults.adapter = require('axios/lib/adapters/http');
也可以在enjoy.service的请求参数里单独指定适配器:
function listCinema(city) { return axios.get(googleBaseURL + city + '&type=cinema&key=' + process.env.GOOGLE_API, { adapter: require('axios/lib/adapters/http') }) }
方案3:Mock第三方API请求(单元测试最佳实践)
单元测试不需要真实调用谷歌地图API,直接Mock axios的返回值即可,既不会触发跨域问题,也不会消耗API配额、不受网络波动影响:
在你的测试文件开头添加Mock逻辑:
const axios = require('axios'); jest.mock('axios'); // 测试用例里指定返回值 test('Status is OK', () => { axios.get.mockResolvedValue({ data: { status: 'OK' } }); return enjoyService.listCinema("nantes").then(res => { expect(res.data.status).toBe('OK'); }); }); test('Status is 404', () => { axios.get.mockRejectedValue(new Error()); return enjoyService.listCinema("X Æ A-XII").catch(err => { expect(err.name).toBe("Error"); }); });
内容的提问来源于stack exchange,提问作者crg
相关产品推荐
相关产品推荐

