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

如何捕获Angular组件生命周期方法抛出的错误并完成测试?

如何测试Angular组件未提供必填输入时的抛出错误行为?

我有一个包含必填输入的Angular组件,当未提供这些输入时会在ngOnInit中抛出错误,组件代码如下:

export class FormValidationMessageComponent implements OnInit {
  @Input() form!: NgForm;
  @Input() field!: NgModel;

  ngOnInit(): void {
    if (typeof this.form === 'undefined') throw new Error(`The 'form' property is not set!`);
    if (typeof this.field === 'undefined') throw new Error(`The 'field' property is not set!`);
  }
}

我尝试编写测试验证这一行为,但当前测试代码会直接抛出错误导致测试失败,测试代码如下:

let component: FormValidationMessageComponent;
let fixture: ComponentFixture<FormValidationMessageComponent>;

beforeEach(() => {
  TestBed.configureTestingModule({
    imports: [FormValidationMessageComponent],
  });
  fixture = TestBed.createComponent(FormValidationMessageComponent);
  component = fixture.componentInstance;
});

it('should throw an error when the `form` input is not provided', () => {
  const onInitSpy = spyOn(component, 'ngOnInit');
  component.field = {} as NgModel;

  fixture.detectChanges(); //Triggers ngOnInit()

  expect(onInitSpy).toThrow();
});

执行测试时会直接抛出以下错误,导致测试不通过:

Error: The 'form' property is not set!

解决方案

要正确捕获ngOnInit中抛出的错误,核心是将触发错误的逻辑包裹在箭头函数中传给expect,让Jasmine在执行该函数时捕获错误。以下是两种可行的测试写法:

方式一:手动调用ngOnInit

直接调用组件的ngOnInit方法,并用箭头函数包裹执行逻辑:

it('should throw an error when the `form` input is not provided', () => {
  component.field = {} as NgModel;
  // 用箭头函数包裹ngOnInit调用,让expect捕获执行时的错误
  expect(() => component.ngOnInit()).toThrowError("The 'form' property is not set!");
});

方式二:通过fixture.detectChanges()触发

如果需要模拟真实组件初始化流程(通过detectChanges触发ngOnInit),同样要将detectChanges调用包裹在箭头函数中:

it('should throw an error when the `form` input is not provided', () => {
  component.field = {} as NgModel;
  // 将detectChanges的执行逻辑传给expect
  expect(() => fixture.detectChanges()).toThrowError("The 'form' property is not set!");
});

测试field未提供的情况

同理,验证field输入缺失的测试代码如下:

it('should throw an error when the `field` input is not provided', () => {
  component.form = {} as NgForm;
  expect(() => component.ngOnInit()).toThrowError("The 'field' property is not set!");
});

关键说明

Jasmine的toThrow()系列方法要求传入一个可执行的函数,只有当这个函数被执行时抛出错误,才能被正确捕获。之前的错误写法是先执行了fixture.detectChanges(),导致错误提前抛出到测试上下文,无法被expect捕获。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.09 03:16:02