使用Jasmine测试Angular HTTP服务报错:期望为AddUserShareModel,实际为SafeSubscriber
解决Angular Jasmine测试中Observable提取值的错误问题
错误原因
subscribe()方法返回的是SafeSubscriber订阅对象,而非Observable发出的实际数据,你把它赋值给result,自然无法匹配AddUserShareModel类型。- 直接调用服务的HTTP方法会发起真实请求,测试应该模拟后端响应,避免依赖外部服务。
解决方案
使用Angular提供的HttpTestingController模拟HTTP请求,同时用RxJS的firstValueFrom将Observable转换为Promise,配合async/await获取数据。
修改后的完整测试代码
import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing'; import { TestBed } from '@angular/core/testing'; import { AddUserShareModel } from 'src/app/shared/models/add.userShare.model'; import { UserShareService } from '../../app/services/userShare.service'; import { firstValueFrom } from 'rxjs'; import { environment } from 'src/environments/environment'; describe('UserShareService', () => { let service: UserShareService; let httpTestingController: HttpTestingController; const mockApiUrl = `${environment.rootUrl}/api/UserShare`; beforeEach(() => { TestBed.configureTestingModule({ imports: [HttpClientTestingModule], providers: [UserShareService], }); service = TestBed.inject(UserShareService); httpTestingController = TestBed.inject(HttpTestingController); }); // 清理未处理的请求,防止测试泄漏 afterEach(() => { httpTestingController.verify(); }); it('should be created', () => { expect(service).toBeTruthy(); }); it("should have defined method addUserShare", () => { expect(service.addUserShare).toBeDefined(); }); it('should add share and return AddUserShareModel', async () => { // 准备测试数据 const testModel = new AddUserShareModel(20, "reciever@email.de", ["guid1", "guid2"]); const mockResponse = new AddUserShareModel(20, "reciever@email.de", ["guid1", "guid2"]); // 将Observable转为Promise,用async/await获取结果 const resultPromise = firstValueFrom(service.addUserShare(testModel)); // 捕获并验证HTTP请求 const req = httpTestingController.expectOne(`${mockApiUrl}/Add`); expect(req.request.method).toBe('PUT'); expect(req.request.body).toEqual(testModel); // 返回模拟响应 req.flush(mockResponse); // 获取结果并断言 const result = await resultPromise; expect(result).toBeTruthy(); expect(result).toBeDefined(); expect(result).toEqual(mockResponse); }); });
关键说明
- HttpTestingController:捕获服务发起的HTTP请求,模拟后端响应,确保测试不依赖真实服务。
- firstValueFrom:RxJS 7+提供的方法,将Observable转换为Promise,配合
async/await优雅处理异步数据(RxJS 6及以下可使用toPromise(),但该方法已废弃)。 - afterEach中的verify():确保所有发起的HTTP请求都被处理,避免测试残留未完成的请求。
- expectOne:匹配对应的请求URL,验证服务调用了正确的接口地址。
额外提示
如果需要宽松匹配对象而非严格匹配类实例,可以用jasmine.objectContaining断言属性:
expect(result).toEqual(jasmine.objectContaining({ daysActive: 20, receiverEmail: "reciever@email.de", documentIds: ["guid1", "guid2"] }));
内容的提问来源于stack exchange,提问作者Antinopolis
相关产品推荐
相关产品推荐

