如何在Jasmine测试中触发服务调用并验证输出长度?
问题解决方案
问题1:触发服务调用的正确方式
原测试里直接替换component.search为新的BehaviorSubject是无效的——组件在ngOnInit中已经基于初始的Subject构建了listItems的数据流管道。正确做法是调用原search Subject的next()方法发送输入值,同时因为代码里用了debounceTime(500),测试时需要用fakeAsync和tick()跳过防抖延迟,确保数据流正常执行。
问题2:验证输出长度的正确姿势
要确保模拟的ListService.getList方法在接收输入"3"时,返回符合预期的单条目数据,再订阅listItems并断言其长度。
修正后的单元测试代码
import { fakeAsync, tick, ComponentFixture, TestBed } from '@angular/core/testing'; import { ReactiveFormsModule } from '@angular/forms'; import { HttpClientTestingModule } from '@angular/common/http/testing'; import { NgSelectModule } from '@ng-select/ng-select'; import { of } from 'rxjs'; import { AppComponent } from './app.component'; import { ListService } from './list.service'; describe('AppComponent', () => { let fixture: ComponentFixture<AppComponent>; let component: AppComponent; let listService: ListService; beforeEach(async () => { await TestBed.configureTestingModule({ imports: [ReactiveFormsModule, HttpClientTestingModule, NgSelectModule], declarations: [AppComponent], providers: [ListService] }).compileComponents(); }); beforeEach(() => { fixture = TestBed.createComponent(AppComponent); component = fixture.componentInstance; listService = TestBed.inject(ListService); fixture.detectChanges(); // 触发ngOnInit初始化数据流 }); it(`should set the length of output observable array as 1`, fakeAsync(() => { // 模拟服务返回:输入"3"时仅返回对应条目 const mockResponse = [{ "id": "3", "name": "Apple" }]; spyOn(listService, 'getList').and.returnValue(of(mockResponse)); // 发送输入值,触发数据流 component.search.next('3'); // 跳过500ms防抖延迟 tick(500); // 订阅并验证结果 component.listItems.subscribe(resp => { expect(resp.length).toBe(1); expect(resp[0].id).toBe('3'); // 额外验证条目正确性 }); })); });
关键修正说明
- 触发输入事件:用
component.search.next('3')给原有Subject发值,复用ngOnInit中已构建的数据流管道,才能触发服务调用。 - 处理防抖延迟:用
fakeAsync包裹测试,tick(500)模拟时间流逝,跳过防抖等待,不用真的等待500ms。 - 匹配模拟数据:让服务在收到
"3"时返回单条目数组,保证断言长度为1的逻辑成立。 - 初始化组件:调用
fixture.detectChanges()触发ngOnInit,确保数据流提前初始化完成,订阅后能正常接收值。
内容的提问来源于stack exchange,提问作者prachi bhamodre
相关产品推荐
相关产品推荐

