Angular 2-Karma测试:Interceptor中popHttpRequest的spy未被调用问题
问题分析与修复方案
嘿,我一眼就发现问题所在了,咱们一步步来拆解:
核心问题:方法名不匹配
你的拦截器代码里实际调用的是loadOverlayService.start()和loadOverlayService.stop(),但在测试代码中,你给LoadOverlayService mock的是pushHttpRequest和popHttpRequest这两个方法——这俩完全是不同的方法!
拦截器里从来没调用过pushHttpRequest和popHttpRequest,所以你的spy自然会记录调用次数为0,这完全符合预期。
两种修复思路
思路1:直接验证拦截器实际调用的方法
既然拦截器里用的是start和stop,那测试里就应该mock并验证这两个方法:
修改测试中的mock创建代码:
mockLoadOverlayService = jasmine.createSpyObj('LoadOverlayService', ['start', 'stop']);
然后在断言部分改成:
expect(mockLoadOverlayService.start.calls.count()).toBe(1, 'start was called once'); expect(mockLoadOverlayService.stop.calls.count()).toBe(1, 'stop was called once');
思路2:关联start/stop与push/popHttpRequest
如果你的LoadOverlayService内部逻辑是start()会调用pushHttpRequest(),stop()会调用popHttpRequest(),那你需要在mock中模拟这个关联关系:
mockLoadOverlayService = jasmine.createSpyObj('LoadOverlayService', ['start', 'stop', 'pushHttpRequest', 'popHttpRequest']); // 模拟start内部调用pushHttpRequest mockLoadOverlayService.start.and.callFake(() => { mockLoadOverlayService.pushHttpRequest(); }); // 模拟stop内部调用popHttpRequest mockLoadOverlayService.stop.and.callFake(() => { mockLoadOverlayService.popHttpRequest(); });
这样当拦截器调用start()和stop()时,对应的push/pop方法也会被触发,你的原断言就能正常工作了。
额外小提示
注意RxJS版本的操作符:如果你用的是RxJS 6及以上版本,do操作符已经被重命名为tap了,虽然旧版本的do还能兼容,但建议统一换成tap以避免潜在问题:
return next.handle(request) .tap( () => {}, // 发出值时的回调,这里不需要处理 () => this.loadOverlayService.stop(), // 错误时停止 () => this.loadOverlayService.stop() // 完成时停止 );
内容的提问来源于stack exchange,提问作者Hidden
相关产品推荐
相关产品推荐

