如何通过Jasmine测试用例‘should recover on fetch error’
问题根因分析
- 你没有对fetch做模拟,第一个指向
/recordszzz的请求实际会返回404或跨域错误,如果你的retrieve()函数没有对fetch的异常做捕获处理,第一个retrieve()调用返回的Promise会变成rejected状态,根本不会执行后续的check回调,自然不会触发你预期的console.log调用,所以第一个断言Expected spy log to have been called会报错。 - 你用
console.log的调用状态作为错误是否触发的判断依据完全不可靠:如果业务代码的错误分支用的是console.error打印日志、或者根本没打日志,都会触发断言失败;你手动加了console.log后如果正常分支也加了日志,第二个Expected spy log to not be called自然也会报错。 - 直接修改
window.path会产生全局副作用,未重置的情况下会影响其他测试用例的执行结果。
修复方案
- 优先使用Jasmine的fetch mock能力模拟接口返回,不要依赖真实后端服务的可用性,直接控制第一个请求返回异常、第二个请求返回正常数据。
- 移除对
console.log的断言,改为直接判断retrieve()的返回状态、或者监听fetch的调用情况作为判断依据。
修正后的测试代码示例
it('should recover on fetch error', function(done){ // 先存下原始path,测试结束后重置,避免副作用 const originalPath = window.path; window.path = "http://localhost:3000/recordszzz"; // 模拟fetch的返回:第一个调用返回错误,第二个调用返回正常数据 spyOn(window, 'fetch').and.callFake((url) => { if (url.includes('recordszzz')) { return Promise.reject(new Error('Fetch failed')); } return Promise.resolve({ json: () => Promise.resolve({/* Object here */}) }); }); // 错误分支的回调 function handleFirstError(err) { // 切换为正常接口地址 window.path = "http://localhost:3000/records"; // 第二次调用retrieve,验证可以正常返回 retrieve().then(function(output){ const expected = {/* Object here */}; expect(output).toEqual(expected); // 重置全局变量 window.path = originalPath; done(); }).catch(done.fail); // 第二次调用失败的话直接标记测试失败 } // 第一次调用,预期进入catch回调 retrieve().catch(handleFirstError); });
内容的提问来源于stack exchange,提问作者Michael Barreiro
相关产品推荐
相关产品推荐

