Angular 5 HTTP单元测试报错Expected no open requests, found 1怎么解决?
解决Angular 5 HTTP单元测试中的
Error: Expected no open requests, found 1问题 嘿,这个问题我太熟了!在Angular的HTTP单元测试里碰到这个错误,本质就是你的测试用例跑完后,还有一个HTTP请求没被HttpTestingController处理掉。别慌,咱们一步步来解决:
问题根源
Angular的HttpClientTestingModule用HttpTestingController来拦截所有真实的HTTP请求,转而用模拟响应代替。但它有个严格的规则:每个被拦截的请求都必须被显式匹配并处理,否则测试结束时就会抛出这个“还有未完成请求”的错误。
结合你的代码修复
从你给出的测试代码片段来看,你在测试DangerService的GET请求,那咱们把缺失的关键步骤补上:
1. 确保注入HttpTestingController
首先在测试块里注入控制器实例,方便后续处理请求:
import { TestBed } from '@angular/core/testing'; import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing'; import { DangerService } from './danger.service'; import { DangerFlag } from '../danger.model'; describe('DataService Tests', () => { let dataService: DangerService; let httpTestingController: HttpTestingController; // 新增控制器实例 beforeEach(() => { TestBed.configureTestingModule({ imports: [HttpClientTestingModule], providers: [DangerService] }); // 获取服务和控制器实例 dataService = TestBed.inject(DangerService); httpTestingController = TestBed.inject(HttpTestingController); }); // 测试用例写在这里 });
2. 完整的GET请求测试示例
每个测试用例都要遵循“调用服务 -> 匹配请求 -> 返回模拟数据 -> 验证请求完成”的流程:
it('should fetch danger flags successfully via GET', () => { // 1. 准备模拟数据 const mockDangerFlags: DangerFlag[] = [ { id: 1, name: 'High Risk', level: 3 }, { id: 2, name: 'Medium Risk', level: 2 } ]; // 2. 调用服务的GET方法(必须订阅,否则请求不会触发) dataService.getDangerFlags().subscribe(flags => { expect(flags).toEqual(mockDangerFlags); // 验证返回数据 }); // 3. 匹配发送的请求(替换成你实际的API地址,支持正则) const req = httpTestingController.expectOne('/api/danger-flags'); expect(req.request.method).toBe('GET'); // 验证请求方法是否正确 // 4. 返回模拟响应 req.flush(mockDangerFlags); // 5. 全局验证所有请求都已处理(关键!) httpTestingController.verify(); });
3. 避免踩坑的小技巧
- 全局验证请求完成:可以把
httpTestingController.verify()放在afterEach里,确保每个测试用例结束后都检查有没有遗漏的请求:afterEach(() => { httpTestingController.verify(); }); - URL匹配要准确:如果你的请求有动态参数(比如
/api/danger-flags?id=1),可以用正则表达式匹配:httpTestingController.expectOne(/\/api\/danger-flags/) - 别忘了订阅Observable:Angular的HTTP请求是冷Observable,只有订阅后才会真正发送请求,没订阅的话控制器也抓不到请求哦。
总结
这个错误就是在提醒你:“喂,还有个HTTP请求没处理呢!”只要确保每个请求都被expectOne匹配、flush返回数据,最后用verify检查,问题就能解决啦。
内容的提问来源于stack exchange,提问作者user1037747




