Angular单元测试出现SPEC HAS NO EXPECTATIONS与Timeout超时错误如何解决
问题根源
你已引入HttpClientTestingModule替换了真实的HTTP请求实现,所有请求都会被拦截为模拟请求,不会自动返回响应。你没有手动触发请求的响应返回,导致sendMessage返回的Observable永远不会触发回调,自然等不到expect执行、也等不到done()触发,最终抛出超时错误,调整超时时间无法解决这个问题。
修复方案
需要搭配HttpTestingController手动处理模拟请求,触发响应返回,同时还可以验证请求的参数、方法是否符合预期。
完整修正后的测试代码
import { TestBed } from '@angular/core/testing'; import { ApiService } from './api.service'; import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing'; describe('ApiService', () => { let service: ApiService; // 声明HttpTestingController实例 let httpTestingController: HttpTestingController; const testData = { name: "fdsgs", sex: "gfjhghj", address:"ghmfgj", county: "ghjdgfhj", contactMethod: ["dfghjsfdghd", "helloworld"], daysAvailable: ["dfghfdgh", "heloo world"], timesAvailable: ["sdfghfgh", "hello world"], aboutPerson: ["stfghfdghd", "sadf"], aboutChildren: ["jdfhjtd", "awert"], questions: "gfhdfgh", howTheyHeardOfUs: ["dfghasg", "fasfg"] }; beforeEach(() => { TestBed.configureTestingModule({ imports: [HttpClientTestingModule], providers: [ApiService] }); service = TestBed.inject(ApiService); // 初始化HttpTestingController httpTestingController = TestBed.inject(HttpTestingController); }); it('should be created', () => { expect(service).toBeTruthy(); }); it(`should post data correctly`, (done: DoneFn)=>{ service.sendMessage(testData).subscribe(res =>{ // 验证返回值和我们flush的模拟值一致 expect(res).toBe('observable value'); done(); }); // 匹配我们发出的POST请求 const mockReq = httpTestingController.expectOne('URL'); // 验证请求方法为POST expect(mockReq.request.method).toBe('POST'); // 验证请求体和我们传入的测试数据一致 expect(mockReq.request.body).toEqual(testData); // 手动触发返回模拟响应,触发subscribe回调 mockReq.flush('observable value'); }); // 每个用例执行后验证所有请求都已处理,没有多余的待处理请求 afterEach(() => { httpTestingController.verify(); }); });
内容的提问来源于stack exchange,提问作者Zedword
相关产品推荐
相关产品推荐

