Angular 5中如何在测试宿主中访问指令的属性与方法?
解决Angular单元测试中访问指令属性和方法的问题
看起来你遇到的核心问题是错误地尝试从测试组件(TestComponent)访问ToggleDirective的属性和方法——这些成员属于指令本身,而非你用来包裹测试模板的空组件。下面是具体的解决思路和修正后的测试代码:
核心思路
要测试ToggleDirective的逻辑,你需要:
- 定位到模板中应用了该指令的DOM元素(也就是
<toggler-toggle>标签对应的元素) - 从这个元素的注入器中获取指令的实例
- 直接操作和断言指令实例的属性与方法
修正后的单元测试代码
首先确保你导入了ToggleDirective(用来查询目标元素):
import { Component } from '@angular/core'; import { TestBed, ComponentFixture } from '@angular/core/testing'; import { By } from '@angular/platform-browser'; import { TogglerModule } from './toggler.module'; // 导入你要测试的指令 import { ToggleDirective } from './toggle.directive'; @Component({ template: ` <toggler> <toggler-toggle>Toggle</toggler-toggle> <toggler-menu> <toggler-item>Sample Item 1</toggler-item> </toggler-menu> </toggler>`, }) class TestComponent {} describe('ToggleDirective', () => { let fixture: ComponentFixture<TestComponent>; let toggleDirective: ToggleDirective; beforeEach(() => { TestBed.configureTestingModule({ imports: [TogglerModule], declarations: [TestComponent], }).compileComponents(); fixture = TestBed.createComponent(TestComponent); fixture.detectChanges(); // 触发初始变更检测,确保指令初始化完成 // 1. 找到应用了ToggleDirective的元素 const toggleElement = fixture.debugElement.query(By.directive(ToggleDirective)); // 2. 从元素的注入器中获取指令实例 toggleDirective = toggleElement.injector.get(ToggleDirective); }); it('should initialize with visible state as false', () => { expect(toggleDirective.visible).toBeFalsy(); }); it('should toggle visible state when clicking the toggle element', () => { const toggleElement = fixture.debugElement.query(By.directive(ToggleDirective)); // 创建模拟点击事件,指定target为toggle元素本身 const clickEvent = new MouseEvent('click', { target: toggleElement.nativeElement }); // 调用指令的点击处理方法 toggleDirective.onVoidClick(clickEvent); fixture.detectChanges(); expect(toggleDirective.visible).toBeTruthy(); }); it('should set visible to false when clicking outside the toggle element', () => { // 先手动设置visible为true,模拟已展开状态 toggleDirective.visible = true; // 创建模拟点击事件,target指向外部元素(比如document.body) const clickEvent = new MouseEvent('click', { target: document.body }); toggleDirective.onVoidClick(clickEvent); fixture.detectChanges(); expect(toggleDirective.visible).toBeFalsy(); }); });
关键细节说明
- 获取指令实例:
By.directive(ToggleDirective)是Angular测试中定位指令宿主元素的标准方式,通过injector.get(ToggleDirective)就能拿到指令的实例,这是访问指令内部成员的唯一正确途径。 - 模拟事件参数:你的
onVoidClick方法依赖event.target判断点击位置,所以必须创建带有正确target的模拟鼠标事件,否则指令逻辑无法正常执行。 - 变更检测:在修改指令状态或触发事件后,调用
fixture.detectChanges()确保组件状态与视图同步,避免断言结果不符合预期。
如果需要测试指令与ToggleService的交互,还可以通过TestBed.provide替换成模拟服务,隔离外部依赖对测试的影响。
内容的提问来源于stack exchange,提问作者GRowing
相关产品推荐
相关产品推荐

