Angular .detectChanges()在角度测试范围内不工作
我的任务是为Angular开发的聊天应用程序编写测试。下面是我目前正在编写测试的Angular模板代码片段:Angular .detectChanges()在角度测试范围内不工作,angular,testing,jasmine,Angular,Testing,Jasmine,我的任务是为Angular开发的聊天应用程序编写测试。下面是我目前正在编写测试的Angular模板代码片段: 检查 设置 本质上,如果组件布尔变量“titleInputIt”为真,则显示“保存标题”按钮,否则显示“设置”按钮。以下是导致问题的测试用例: it('应存在保存标题按钮',()=>{ component.titleInputIt=true; fixture.detectChanges(); expect(fixture.nativeElement.querySelector(“#保
检查
设置
本质上,如果组件布尔变量“titleInputIt”为真,则显示“保存标题”按钮,否则显示“设置”按钮。以下是导致问题的测试用例:
it('应存在保存标题按钮',()=>{
component.titleInputIt=true;
fixture.detectChanges();
expect(fixture.nativeElement.querySelector(“#保存标题按钮”).not.toBe(null);
});
我只是“模拟”组件变量,调用.detectChanges(),然后测试按钮是否存在。但是,测试失败,出现“预期null不为null”
通过各种console.log调用,我确认component.titleInputIt已正确设置为true,但fixture.nativeElement未包含正确的按钮
我注意到一些事情:
- 如果我将'component.titleInputIt=true'行移到beforeach中并从测试中删除它,以及detectChanges()调用,则测试通过
beforeach(()=>{ fixture=TestBed.createComponent(TestComponent); 组件=fixture.componentInstance; component.titleInputIt=true fixture.detectChanges(); debugElement=fixture.debugElement; }); 它('应存在保存标题按钮',()=>{ expect(fixture.nativeElement.querySelector(“#保存标题按钮”).not.toBe(null); });
- 如果我从beforeach()中删除.detectChanges()调用,并将其保留在测试用例中,则测试通过
it('应显示不同的测试标题',()=>{
component.title='测试标题';
fixture.detectChanges();
expect(h1.textContent).toContain('testtitle');
});
事实证明,这是由于在组件中使用了ChangeDetectionStrategy.OnPush
。使用OnPush
只允许您调用.detectChanges()
一次,因此后续调用将无法执行任何操作。我对Angular不太熟悉,无法完全理解原因
通过在我的测试台配置中重写ChangeDetectionStrategy
,我能够产生所需的行为
TestBed.configureTestingModule({
进口:[],
声明:[TestComponent],
提供者:[]
})
.overrideComponent(TestComponent{
集合:{changeDetection:ChangeDetectionStrategy.Default}
})
.compileComponents();
此处提供的答案解决了问题。然而,我认为还有另一种方法可以防止UI上出现进一步的问题。我遇到的问题与问题中描述的问题类似,这意味着在HTML上测试特定字符串时,我找不到它。即使在运行代码时,它的措辞很好,但在测试它时,UI并没有相应地更新
我要做的是:
要将ChangeDetectorRef
注入.ts
文件:
constructor(private changeDetector: ChangeDetectorRef) {}
并在需要时呼叫:
this.changeDetector.markForCheck();
我知道这个问题由来已久,但我最近遇到了同样的问题,一个旋转器会在业力页面上不断旋转,因为变化检测只发生一次。我的解决方法是调用fixture.detectChanges(true)还是fixture.autoDetectChanges(true)
在每个(()=>{
fixture=TestBed.createComponent(TestComponent);
组件=fixture.componentInstance;
component.titleInputIt=true
//“detectChanges”将仅测试onPush事件:
//fixture.detectChanges();
//“自动检测更改”将持续检查更改,直到测试完成。
//这比较慢,但对于某些UI更改是必需的
夹具。自动检测更改(真);
debugElement=fixture.debugElement;
});
在我的情况下,由于异步加载,我需要使用fixture.whenStable,而不仅仅是fixture.detectChanges,例如
it('test description', async(async () => {
await fixture.whenStable();
}));
更好的方法是只使用
ChangeDetectionStrategy.Default
策略在规范中编写包装器组件,并通过父组件实例(即包装器组件)在规范中测试要测试的实际组件(即子组件)
通过使用
fixture.debugElement.query(by.css('your-Child-selector'))可以通过父对象的fixture.debugElement
访问子实例及其本机元素。
对不起,答案有点误导OnPush
策略告诉您,当其父组件更新其中一个组件输入时,仅标记组件以供检查。在测试中手动设置属性不能被Angular跟踪,因此在DOM中看不到任何更改。如果titleInputIt
是一个输入,则在测试中创建一个主机组件,并将其属性绑定到titleInputIt
。仅使用OnPush的语句只允许您一次调用.detectChanges()
不是100%正确的。在这之前,应该有东西标记你的部件以供检查。这有点像是把婴儿和洗澡水一起扔掉。有很好的理由可以解释为什么您希望使用手动detectChanges
策略,因此简单地抛弃所有这些并不是正确的解决方案。简单地将组件简化为便于测试是一个坏主意