Angular 14中如何测试StoreService的HTTP删除API及模拟成功调用?
测试Angular 14中调用HTTP删除API的StoreService
一、模拟封装的HTTP删除API服务(返回Observable)的成功调用
假设我们有一个封装HTTP请求的ApiService,其中的删除方法返回Observable:
// api.service.ts import { HttpClient } from '@angular/common/http'; import { Injectable } from '@angular/core'; import { Observable } from 'rxjs'; @Injectable({ providedIn: 'root' }) export class ApiService { constructor(private http: HttpClient) {} deleteItem(id: number): Observable<{ success: boolean }> { return this.http.delete<{ success: boolean }>(`/api/items/${id}`); } }
在测试中,我们可以通过Jasmine的createSpyObj创建ApiService的模拟对象,让其deleteItem方法返回一个包装了成功响应的Observable:
// store.service.spec.ts import { TestBed } from '@angular/core/testing'; import { StoreService } from './store.service'; import { ApiService } from './api.service'; import { of } from 'rxjs'; describe('StoreService', () => { let storeService: StoreService; let apiServiceSpy: jasmine.SpyObj<ApiService>; beforeEach(() => { // 创建ApiService的模拟实例,指定要mock的方法 const spy = jasmine.createSpyObj('ApiService', ['deleteItem']); TestBed.configureTestingModule({ providers: [ StoreService, { provide: ApiService, useValue: spy } ] }); storeService = TestBed.inject(StoreService); apiServiceSpy = TestBed.inject(ApiService) as jasmine.SpyObj<ApiService>; }); // 测试成功调用删除API的场景 it('should process successful deletion via ApiService', (done) => { const mockSuccessRes = { success: true }; // 设置mock方法返回成功的Observable apiServiceSpy.deleteItem.and.returnValue(of(mockSuccessRes)); storeService.deleteItem(1).subscribe({ next: (res) => { expect(res).toEqual(mockSuccessRes); // 验证API方法被正确调用,参数符合预期 expect(apiServiceSpy.deleteItem).toHaveBeenCalledWith(1); done(); }, error: () => { fail('删除请求应成功,不应进入错误分支'); done(); } }); }); });
二、测试StoreService的完整删除逻辑
如果StoreService在调用API后有额外业务逻辑(比如更新本地数据),需要同时验证这些逻辑:
StoreService实现示例
// store.service.ts import { Injectable } from '@angular/core'; import { ApiService } from './api.service'; import { Observable } from 'rxjs'; import { tap } from 'rxjs/operators'; @Injectable({ providedIn: 'root' }) export class StoreService { private localItems: { id: number; name: string }[] = [{ id: 1, name: '测试项' }]; constructor(private apiService: ApiService) {} getLocalItems() { return [...this.localItems]; } deleteItem(id: number): Observable<{ success: boolean }> { return this.apiService.deleteItem(id).pipe( tap(() => { // 删除本地数据 this.localItems = this.localItems.filter(item => item.id !== id); }) ); } }
对应的测试用例
// 验证本地数据是否被正确删除 it('should remove item from local storage after successful deletion', (done) => { apiServiceSpy.deleteItem.and.returnValue(of({ success: true })); // 初始状态校验 expect(storeService.getLocalItems().length).toBe(1); storeService.deleteItem(1).subscribe({ next: () => { expect(storeService.getLocalItems().length).toBe(0); done(); }, error: () => { fail('删除请求失败'); done(); } }); }); // 使用fakeAsync简化异步测试 it('should handle deletion with fakeAsync', fakeAsync(() => { const mockRes = { success: true }; apiServiceSpy.deleteItem.and.returnValue(of(mockRes)); let response: { success: boolean } | undefined; storeService.deleteItem(1).subscribe(res => response = res); tick(); // 触发Observable执行 expect(response).toEqual(mockRes); expect(apiServiceSpy.deleteItem).toHaveBeenCalledWith(1); expect(storeService.getLocalItems().length).toBe(0); }));
内容的提问来源于stack exchange,提问作者Randy
相关产品推荐
相关产品推荐

