Angular单元测试:如何验证订阅触发私有方法调用?
Angular单元测试:验证私有方法
createUser是否被调用 我有一个Angular组件,它订阅了一个发送布尔值的Service。当值为true时,应该调用私有方法createUser,但我无法在单元测试中验证该方法是否被调用。
组件私有方法createUser代码
private createUser(){ this.submitForm = false; this.userForm.markAllAsTouched(); if(this.userForm.invalid){ this.submitForm = true; this.formulaireService.setValidForm(false); this.formulaireService.setDisableButton(false); return; } let user = { name: this.userForm.controls['name'].value, age: this.userForm.controls['age'].value } }
组件ngOnInit中的订阅代码
this.subscriptionInitForm = this.formulaireService.sendInitForm$.subscribe((val) => { if(val){ this.createUser(); } });
当前单元测试代码
it('form is valid', fakeAsync(()=> { component.userForm.get('name')?.setValue('NAME'); component.userForm.get('age')?.setValue('45'); let service = fixture.debugElement.injector.get(UserService); service.setSendInitForm(true); tick(500); service.sendInitForm$.subscribe((res) => { expect(component.user.name).toEqual('NAME '); }); flush(); })
解决方案
方法1:直接监听私有方法调用
利用spyOn<any>绕过私有成员的访问限制,直接监听createUser的调用:
it('should call createUser when sendInitForm$ emits true', fakeAsync(() => { // 初始化表单为有效状态 component.userForm.get('name')?.setValue('NAME'); component.userForm.get('age')?.setValue('45'); // 监听组件的私有方法 const createUserSpy = spyOn<any>(component, 'createUser'); // 获取Service并触发值发送 const service = fixture.debugElement.injector.get(UserService); service.setSendInitForm(true); // 处理异步流并触发变更检测 tick(); fixture.detectChanges(); // 验证方法是否被调用 expect(createUserSpy).toHaveBeenCalled(); }));
方法2:通过验证副作用间接确认调用
如果不想直接监听私有方法,可以验证createUser执行后的副作用:
it('should execute createUser logic when sendInitForm$ emits true', fakeAsync(() => { component.userForm.get('name')?.setValue('NAME'); component.userForm.get('age')?.setValue('45'); const service = fixture.debugElement.injector.get(UserService); // 监听Service方法,确认表单有效时不会触发该分支 const setValidFormSpy = spyOn(service, 'setValidForm'); service.setSendInitForm(true); tick(); fixture.detectChanges(); // 验证表单已被标记为触碰 expect(component.userForm.touched).toBeTrue(); // 验证无效分支未执行 expect(setValidFormSpy).not.toHaveBeenCalled(); // 若将user赋值给组件公共属性,可直接验证值 // expect(component.user.name).toEqual('NAME'); }));
原测试代码的问题修正
- 订阅
sendInitForm$的时机太晚,应在触发值之前处理异步流 - 无需等待500ms,
tick()无参数即可处理所有待完成的异步操作 createUser中仅创建了局部变量user,未赋值给组件的user属性,这是原断言失败的核心原因
内容的提问来源于stack exchange,提问作者dna
相关产品推荐
相关产品推荐

