Angular中使用Cypress组件测试Stub子组件
在Cypress组件测试中隔离子组件测试Angular父组件
需求背景
已有一个包含app-child-1和app-child-2两个复杂子组件的Angular父组件,子组件功能已通过Cypress组件测试验证。现在需要完全隔离子组件,单独测试父组件的核心逻辑(比如底部提交按钮的禁用规则)。
解决方案:Mock子组件+Stub属性
由于父组件通过@ViewChild获取子组件实例,并依赖子组件的child1Form、child2Form属性控制按钮状态,我们可以通过创建极简Mock子组件+Cypress Stub模拟属性的方式彻底隔离依赖:
1. 定义Mock子组件
创建仅匹配选择器的空组件,无需实现子组件的复杂逻辑:
// 测试文件内临时定义Mock组件 import { Component } from '@angular/core'; import { FormGroup } from '@angular/forms'; @Component({ selector: 'app-child-1', template: '' // 空模板,无需渲染内容 }) class MockChild1Component { child1Form = {} as FormGroup; // 仅保留父组件需要的属性 } @Component({ selector: 'app-child-2', template: '' }) class MockChild2Component { child2Form = {} as FormGroup; }
2. 编写测试逻辑
挂载父组件时使用Mock组件,通过cy.stub模拟子组件的form.valid属性,验证父组件的按钮状态:
import { ParentComponent } from './parent.component'; cy.mount(ParentComponent, { declarations: [MockChild1Component, MockChild2Component] }).then(({ component, fixture }) => { // Stub子组件1的form.valid属性 const child1ValidStub = cy.stub().as('child1Valid'); component.child1Component.child1Form = { valid: child1ValidStub } as any; // Stub子组件2的form.valid属性 const child2ValidStub = cy.stub().as('child2Valid'); component.child2Component.child2Form = { valid: child2ValidStub } as any; // 场景1:两个表单都无效 → 按钮禁用 child1ValidStub.returns(false); child2ValidStub.returns(false); fixture.detectChanges(); // 触发Angular变更检测 cy.get('button').should('be.disabled'); // 场景2:两个表单都有效 → 按钮启用 child1ValidStub.returns(true); child2ValidStub.returns(true); fixture.detectChanges(); cy.get('button').should('not.be.disabled'); // 场景3:仅一个表单有效 → 按钮仍禁用 child1ValidStub.returns(true); child2ValidStub.returns(false); fixture.detectChanges(); cy.get('button').should('be.disabled'); });
注意事项
- 父组件模板存在拼写错误:
child2From.valid应为child2Form.valid,需先修正该错误,否则测试逻辑会不符合预期。 - 如果父组件
ngOnInit中有依赖子组件的逻辑,需要在Stub属性后手动调用component.ngOnInit()并触发变更检测。
内容的提问来源于stack exchange,提问作者Ken
相关产品推荐
相关产品推荐

