Jasmine运行HTTP请求测试报TypeError: Failed to fetch如何解决
问题根因
报错是三个问题叠加导致的:
- 运行环境不匹配:你当前是通过Karma在浏览器环境跑Jasmine测试,代码中引入的
http是Node.js专属原生模块,浏览器本身不支持。browserify打包时自动给该模块做的polyfill是基于浏览器fetch API实现的,才会抛出TypeError: Failed to fetch错误。 - 代码笔误:第一行写的是
const https = require('http');,引入的是http模块却赋值给https变量,本身就存在引用错误。 - 逻辑缺陷:Promise在请求刚发起时就直接执行
resolve(),没有等待响应返回或错误捕获完成,测试不会等请求结果就执行完毕,断言完全不生效。如果坚持在浏览器环境跑,还会遇到跨域拦截:Karma默认运行在9876端口,请求3000端口的接口违反浏览器同源策略,会被直接拦截。
修复方案
根据测试场景二选一即可:
方案1:纯Node环境跑后端接口测试(推荐)
测本地服务接口不需要走浏览器环境,直接用jasmine命令跑纯Node环境测试即可,不需要browserify打包,原生http模块可直接调用。修正后的完整代码如下:
// 修正模块引入的笔误,变量名和引入模块保持一致 const http = require('http'); const base_url = "http://localhost:3000/"; function testAsync(){ return new Promise((resolve, reject)=>{ http.get(base_url, res => { let data = []; const headerDate = res.headers?.date || 'no response date'; console.log('Status Code:', res.statusCode); console.log('Date in Response header:', headerDate); res.on('data', chunk => { data.push(chunk); }); res.on('end', () => { // 等响应数据全部接收完成再返回结果 resolve({ statusCode: res.statusCode, rawData: Buffer.concat(data).toString() }); }); }).on('error', err => { console.log('Request Error: ', err); // 请求出错时抛出异常,不要直接resolve,否则测试无法捕获错误 reject(err); }); }); } describe("Hello World Server", function() { describe("GET /", function() { it("returns status code 200", async function() { console.log("before http get"); const res = await testAsync(); // 补充实际断言逻辑,否则测试无校验意义 expect(res.statusCode).toBe(200); console.log("after http get"); }); }); });
跑测试前先确保本地3000端口的服务已经正常启动。
方案2:浏览器环境跑测试
如果必须在Karma的浏览器环境执行测试,做两处修改:
- 弃用Node原生http模块,直接用浏览器原生fetch或者axios等兼容浏览器的请求库发请求
- 给3000端口的后端服务配置CORS响应头,允许
http://localhost:9876来源的跨域请求
修正后的测试代码示例:
const base_url = "http://localhost:3000/"; async function testAsync(){ const res = await fetch(base_url); return { statusCode: res.status, rawData: await res.text() } } describe("Hello World Server", function() { describe("GET /", function() { it("returns status code 200", async function() { console.log("before http get"); const res = await testAsync(); expect(res.statusCode).toBe(200); console.log("after http get"); }); }); });
内容的提问来源于stack exchange,提问作者Hindumathy S
相关产品推荐
相关产品推荐

