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

如何编写Jasmine单元测试覆盖Angular mat-autocomplete的Observable过滤逻辑

Angular中测试带pipe操作的Observable方法方案

你当前测试未覆盖pipe后续逻辑的核心原因是:Observable是懒执行的,只有当你主动订阅返回的Observable实例时,pipe中定义的操作符逻辑才会实际运行。你现有代码只调用了dataFilter()方法拿到了Observable对象,没有触发订阅,因此内部的map、过滤逻辑全程没有执行。


正确测试实现

方式1:Jasmine done回调(通用异步场景)

// 先定义测试用模拟数据源
const MOCK_DATA = [
  { foo: 'Apple' },
  { foo: 'Banana' },
  { foo: 'Cherry' },
  { foo: 'Apricot' }
];

it('should return all data when filter value is empty', (done) => {
  getApiSpy.get.and.returnValue(of(MOCK_DATA));
  // 订阅返回的Observable触发内部逻辑执行
  component.dataFilter('').subscribe(filteredData => {
    expect(getApiSpy.get).toHaveBeenCalled();
    // 空字符串应该返回全部原始数据
    expect(filteredData.length).toBe(MOCK_DATA.length);
    expect(filteredData).toEqual(MOCK_DATA);
    done(); // 通知Jasmine异步测试完成
  });
});

it('should return filtered data match the input value', (done) => {
  getApiSpy.get.and.returnValue(of(MOCK_DATA));
  // 测试过滤包含ap的项
  component.dataFilter('ap').subscribe(filteredData => {
    expect(getApiSpy.get).toHaveBeenCalled();
    // 预期返回Apple、Apricot两个匹配项
    expect(filteredData.length).toBe(2);
    expect(filteredData.map(item => item.foo)).toEqual(['Apple', 'Apricot']);
    done();
  });
});

方式2:Angular fakeAsync + tick(同步写法更简洁)

import { fakeAsync, tick } from '@angular/core/testing';

it('should return filtered data match the input value', fakeAsync(() => {
  getApiSpy.get.and.returnValue(of(MOCK_DATA));
  let filteredResult: any[] = [];
  component.dataFilter('ap').subscribe(res => filteredResult = res);
  tick(); // 触发所有微任务执行
  expect(filteredResult.length).toBe(2);
  expect(filteredResult.map(item => item.foo)).toEqual(['Apple', 'Apricot']);
}));

方式3:RxJS 7+ async/await写法

借助firstValueFrom/lastValueFrom可以用async/await语法简化异步逻辑:

import { firstValueFrom } from 'rxjs';

it('should return filtered data match the input value', async () => {
  getApiSpy.get.and.returnValue(of(MOCK_DATA));
  const filteredResult = await firstValueFrom(component.dataFilter('ap'));
  expect(filteredResult.length).toBe(2);
  expect(filteredResult.map(item => item.foo)).toEqual(['Apple', 'Apricot']);
});

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.25 08:54:08