You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Angular 异步输入管道与HttpClient模拟服务的单元测试实现问题

修正后的单元测试实现

你的测试代码核心问题是混用了fakeAsync和Promise.then语法,导致大部分断言逻辑没有实际执行,同时也存在变更检测时机、选择器适配错误的问题,以下是完整可运行的实现:

前置准备(先定义测试用模拟数据)

// 提前定义模拟返回数据
const testBandsRes = {
  bands: [
    { id: 1, name: 'The Beatles' },
    { id: 2, name: 'The Rolling Stones' }
  ]
};

测试用例实现

it('should search for bands starting with "The" and validate all flows', fakeAsync(async () => {
  // 1. 获取输入框元素并输入"The"
  const inputHarness = await loader.getHarness(MatInputHarness);
  await inputHarness.setValue('The');
  fixture.detectChanges();

  // 2. 校验加载指示器正常展示
  const loadingSpinner = fixture.debugElement.query(By.css('mat-spinner'));
  expect(loadingSpinner).toBeTruthy();
  expect(component.loading).toBeTrue();

  // 3. 等待debounceTime 300ms触发服务调用,beforeEach中已经完成服务mock,无需重复定义
  tick(300);
  // 等待mock服务的异步返回完成
  tick();
  fixture.detectChanges();

  // 4. 校验加载指示器正常隐藏
  expect(component.loading).toBeFalse();
  expect(fixture.debugElement.query(By.css('mat-spinner'))).toBeFalsy();

  // 5. 校验返回的选项正常展示
  const autocomplete = await loader.getHarness(MatAutocompleteHarness);
  const options = await autocomplete.getOptions();
  expect(options.length).toBe(2);
  expect(await options[0].getText()).toBe('The Beatles');
  expect(await options[1].getText()).toBe('The Rolling Stones');

  // 6. 可选:选中选项校验formControl取值
  await options[0].click();
  fixture.detectChanges();
  expect(component.formControl.value).toEqual(testBandsRes.bands[0]);

  // 清理剩余异步任务避免报错
  discardPeriodicTasks();
}));

关键修改说明

  • 用async/await配合fakeAsync处理Material Harness的异步方法,避免回调丢失
  • 严格按照流的执行顺序调用tick(),分别处理debounceTime等待和服务异步返回
  • 每次异步操作完成后调用fixture.detectChanges()同步UI状态
  • 使用官方的MatAutocompleteHarness获取选项,避免选择器适配不同版本Material的问题

内容的提问来源于stack exchange,提问作者Max

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.08 02:24:01