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

如何为含if else的MatSelectChange方法编写单元测试实现100%覆盖率

selectionChanged方法100%覆盖率测试方案

要拿到100%代码覆盖率,核心是把方法里所有语句、所有分支路径全跑到,这个方法一共3条可执行路径,把依赖的service做个mock,写3个用例就能全覆盖,具体如下:

测试前准备

先把方法里依赖的service做mock,给doSomething、doSomethingElse两个方法插桩打spy,一来不用真的跑service里的业务逻辑,二来能方便判断方法到底有没有被调用。不用费劲构造真实的MatSelectChange实例,直接写个带value属性的普通对象,强转成MatSelectChange类型当入参就行,完全符合TS类型要求,测试跑起来也更快。

具体测试用例

三个用例对应三条执行路径,缺一个都拿不到100%覆盖率:

  • 入参value等于'1'的场景
    造个value为'1'的mock入参,调用selectionChanged之后,检查service.doSomething是不是刚好被调用了1次,同时service.doSomethingElse完全没被调用。
  • 入参value等于'2'的场景
    造个value为'2'的mock入参,调用方法之后,检查service.doSomethingElse刚好被调用1次,service.doSomething完全没被调用。
  • 入参value既不是'1'也不是'2'的场景
    这是大部分人会漏的隐式分支——两个if判断都不命中的情况,随便选个非'1'/'2'的值当入参就行,比如'3'、null、undefined、空字符串都可以,调用方法之后检查两个service方法都没被调用。

参考测试代码(Angular + Jasmine环境)

// 先mock依赖的service
const mockService = jasmine.createSpyObj('TargetService', ['doSomething', 'doSomethingElse']);
let component: TestComponent;

beforeEach(() => {
  TestBed.configureTestingModule({
    providers: [
      TestComponent,
      { provide: TargetService, useValue: mockService }
    ]
  });
  component = TestBed.inject(TestComponent);
});

it('入参value为1时,调用service.doSomething', () => {
  // 重置spy调用记录,避免其他用例的调用结果干扰当前断言
  mockService.doSomething.calls.reset();
  mockService.doSomethingElse.calls.reset();
  const mockSelectEvent = { value: '1' } as MatSelectChange;
  component.selectionChanged(mockSelectEvent);
  expect(mockService.doSomething).toHaveBeenCalledTimes(1);
  expect(mockService.doSomethingElse).not.toHaveBeenCalled();
});

it('入参value为2时,调用service.doSomethingElse', () => {
  mockService.doSomething.calls.reset();
  mockService.doSomethingElse.calls.reset();
  const mockSelectEvent = { value: '2' } as MatSelectChange;
  component.selectionChanged(mockSelectEvent);
  expect(mockService.doSomethingElse).toHaveBeenCalledTimes(1);
  expect(mockService.doSomething).not.toHaveBeenCalled();
});

it('入参value为其他值时,不调用任何service方法', () => {
  mockService.doSomething.calls.reset();
  mockService.doSomethingElse.calls.reset();
  // 这里选'3'当测试值,换成null/undefined等边界值也可以
  const mockSelectEvent = { value: '3' } as MatSelectChange;
  component.selectionChanged(mockSelectEvent);
  expect(mockService.doSomething).not.toHaveBeenCalled();
  expect(mockService.doSomethingElse).not.toHaveBeenCalled();
});

补个提醒:哪怕你业务上能100%保证下拉选项只会传'1'和'2',第三个用例也得写。覆盖率统计是按代码实际的分支节点算的,和你业务上的入参约束没关系,只有跑到两个if都不命中的路径,分支覆盖率才能到100%。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.18 16:15:44