使用JEST和nock测试时出现‘Cross origin null forbidden’错误
解决Jest测试中nock模拟接口出现"Cross origin null forbidden"的问题
你遇到的这个跨域错误,核心原因是nock默认只拦截Node.js原生http/https模块发起的请求,但你的代码使用的是浏览器环境的fetch(Jest默认用jsdom模拟浏览器),导致nock没拦住真实的请求,最终触发了跨域限制。下面给你几个可行的解决方案:
方案一:让nock能拦截fetch请求
nock本身不直接支持浏览器的fetch API,但可以通过替换成node-fetch来让nock生效——因为node-fetch底层依赖Node.js的http模块,刚好在nock的拦截范围内:
- 先安装node-fetch作为开发依赖:
npm install node-fetch --save-dev
- 在你的测试文件顶部,把全局的
fetch替换为node-fetch:
import { get } from './project'; import nock from 'nock'; global.fetch = require('node-fetch'); const $API = 'https://your-api-url.com'; // 确保这里和你服务代码里的$API完全一致 test('fetch project data with nock', async () => { const fetchNockProject = nock($API) .get('/projects/1') .reply(200, { id: 1, name: 'Mocked Project' }); const data = await get(1); expect(data).toEqual({ id: 1, name: 'Mocked Project' }); expect(fetchNockProject.isDone()).toBe(true); // 验证nock确实拦截了请求 });
方案二:直接用Jest模拟fetch(无需nock)
如果不想额外依赖nock,也可以直接用Jest的mock功能来模拟fetch,这种方式更轻量灵活:
import { get } from './project'; // 全局mock fetch函数 global.fetch = jest.fn(() => Promise.resolve({ json: () => Promise.resolve({ id: 1, name: 'Mocked Project' }) }) ); test('get project data correctly', async () => { const $API = 'https://your-api-url.com'; const data = await get(1); // 验证fetch被调用的参数是否符合预期 expect(fetch).toHaveBeenCalledWith(`${$API}/projects/1`, expect.objectContaining({ mode: 'cors', headers: { 'Accept': 'application/json', 'Content-Type': 'application/json' } })); expect(data).toEqual({ id: 1, name: 'Mocked Project' }); });
方案三:切换Jest测试环境到Node.js
如果你的服务代码本来是为Node.js环境编写的(只是测试时默认用了jsdom),可以直接把Jest的测试环境改成node,这样nock就能正常拦截请求了:
修改你的jest.config.js(如果没有就新建一个):
module.exports = { testEnvironment: 'node' };
注意:切换到Node环境后,全局没有内置fetch,所以需要在代码里引入node-fetch,或者在测试文件里提前polyfill。
额外注意点
- 确保你测试代码里的
$API变量和服务代码里的完全一致,nock对URL的匹配是严格的(包括协议、端口、路径),哪怕有细微差异都会导致拦截失败。 - 如果你用环境变量定义
$API,要确保测试时环境变量已经正确加载(比如用dotenv包)。
内容的提问来源于stack exchange,提问作者MarJano
相关产品推荐
相关产品推荐

