如何捕获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
相关产品推荐
相关产品推荐

