Angular测试:如何正确覆盖组件onChange方法的所有IF判断分支
问题原因
你原来的测试存在几个逻辑错误,导致分支无法触发:
onChange方法第一行就会把selectedType重置为typeCtrl.value,你手动给selectedType赋值的操作会在onChange调用后被覆盖,完全不生效- 你在测试中手动调用了
loadOrg/loadRep等方法,而不是验证onChange是否自动触发了这些方法,测试逻辑无效 - 拼写错误:
val = 'All;缺少闭合单引号,onChange中All分支调用的是data()方法,你spy的却是fetch,自然验证失败 - 你给
orgCtrl赋值,但onChange读取的是typeCtrl的value,两者完全不匹配
正确测试代码
建议把每个分支拆分为独立的测试用例,可读性和排查问题的效率更高:
// 先给所有需要验证的方法添加spy beforeEach(() => { spyOn(component, 'loadOrg').and.callThrough(); spyOn(component, 'loadRep').and.callThrough(); spyOn(component, 'loadTeis').and.callThrough(); spyOn(component, 'data').and.callThrough(); }); it('should call loadOrg when selected type is Org', () => { // 给onChange读取的typeCtrl赋值,而不是手动改selectedType component.typeCtrl.setValue('Org'); component.onChange(); expect(component.selectedType).toBe('Org'); expect(component.loadOrg).toHaveBeenCalled(); }); it('should call loadRep when selected type is Rep', () => { component.typeCtrl.setValue('Rep'); component.onChange(); expect(component.selectedType).toBe('Rep'); expect(component.loadRep).toHaveBeenCalled(); }); it('should call loadTeis when selected type is Teis', () => { component.typeCtrl.setValue('Teis'); component.onChange(); expect(component.selectedType).toBe('Teis'); expect(component.loadTeis).toHaveBeenCalled(); }); it('should call data when selected type is All', () => { component.typeCtrl.setValue('All'); component.onChange(); expect(component.selectedType).toBe('All'); expect(component.data).toHaveBeenCalled(); });
如果你要保留单用例的写法,修正后如下:
it('call onChange and cover all branches', () => { // 先spy所有要验证的方法 const spyLoadOrg = spyOn(component, 'loadOrg').and.callThrough(); const spyLoadRep = spyOn(component, 'loadRep').and.callThrough(); const spyLoadTeis = spyOn(component, 'loadTeis').and.callThrough(); const spyData = spyOn(component, 'data').and.callThrough(); // 测试Org分支 component.typeCtrl.setValue('Org'); component.onChange(); expect(component.selectedType).toEqual('Org'); expect(spyLoadOrg).toHaveBeenCalled(); // 测试Rep分支 component.typeCtrl.setValue('Rep'); component.onChange(); expect(component.selectedType).toEqual('Rep'); expect(spyLoadRep).toHaveBeenCalled(); // 测试Teis分支 component.typeCtrl.setValue('Teis'); component.onChange(); expect(component.selectedType).toEqual('Teis'); expect(spyLoadTeis).toHaveBeenCalled(); // 测试All分支 component.typeCtrl.setValue('All'); component.onChange(); expect(component.selectedType).toEqual('All'); expect(spyData).toHaveBeenCalled(); });
补充说明
如果你的typeCtrl是表单控件,赋值后需要同步视图可以加fixture.detectChanges(),纯逻辑测试的情况下不需要,直接调用onChange即可覆盖所有分支。
内容的提问来源于stack exchange,提问作者user6067069
相关产品推荐
相关产品推荐

