在Angular 2中测试推送组件

在Angular 2中测试推送组件,angular,testing,angular-cli,Angular,Testing,Angular Cli,使用OnPush更改检测策略测试组件时遇到问题 测试是这样的 it('should show edit button for featured only for owners', () => { let selector = '.edit-button'; component.isOwner = false; fixture.detectChanges(); expect(fixture.debugElement.query(By.css(selecto

使用
OnPush
更改检测策略测试组件时遇到问题

测试是这样的

it('should show edit button for featured only for owners', () => {
    let selector = '.edit-button';

    component.isOwner = false;
    fixture.detectChanges();

    expect(fixture.debugElement.query(By.css(selector))).toBeFalsy();

    component.isOwner = true;
    fixture.detectChanges();

    expect(fixture.debugElement.query(By.css(selector))).toBeTruthy();
});

如果我使用
Default
策略,它会按预期工作,但是使用
OnPush
调用
detectChanges
不会重新请求对
isOwner
的更改。我遗漏了什么吗?

如果您查看这个伟大的@Günter的答案,那么您可以使用事件处理程序来解决它,如:

const fixture = TestBed.overrideComponent(TestComponent, {set: {host: { "(click)": "dummy" }}}).createComponent(TestComponent);
// write your test
fixture.debugElement.triggerEventHandler('click', null);
fixture.detectChanges();

这里是您需要告诉angular您更改了组件的输入属性。在理想的世界里,你会取代

component.isOwner = false;
fixture.detectChanges();


不幸的是,这不起作用,因为angular()中有一个bug。您可以使用此处描述的一种变通方法。

类似于公开ChangeDetectionRef的变通方法,但由于这仅用于测试,我刚刚从v2.6中关闭了
/@ts ignore
标志,因此可以将ref保留为私有

这可能如何工作的示例:

import{ChangeDetectionStrategy,ChangeDetectorRef,Component,Input}来自“@angular/core”;
从“@angular/core/testing”导入{TestBed};
从“@angular/platform browser”导入{By}”;
从“./widget.component”导入{WidgetComponent};
@组成部分({
changeDetection:ChangeDetectionStrategy.OnPush,
模板:``,
});
导出类PushyComponent{
@Input()widgetEnabled=true;
构造函数(私有cdr:ChangeDetectorRef){}
//这里实际使用this.cdr的方法。。。
}
TestBed.configureTestingModule({
声明:[PushyComponent,WidgetComponent],
}).compileComponents();
const fixture=TestBed.createComponent(PushyComponent);
常量组件=fixture.componentInstance;
fixture.detectChanges();
expect(component.widgetEnabled).toBe(true);
设el=fixture.debugElement.query(By.directive(WidgetComponent));
expect(el.toBeTruthy();
component.widgetEnabled=false;
//@ts ignore:为了进行测试,我们需要访问私有cdr以检测更改
component.cdr.detectChanges();
el=fixture.debugElement.query(By.directive(WidgetComponent));
期望(el.toBeFalsy();

这个问题很容易解决。。。

TestBed.configureTestingModule({
声明:[MyComponent]
})
.overrideComponent(MyComponent{
集合:{changeDetection:ChangeDetectionStrategy.Default}
})
.compileComponents();
请记住,这种方法可能会掩盖一些更改检测问题


信用证:

看看这个帖子,这是你的测试,我用你的评论中的解决方案进行了测试。虽然这可能更“干净”,但它更麻烦,因此我宁愿将此黑客包在助手中,并希望将来有更好的解决方案:)谢谢!请注意,
overrideComponent
如果在测试中使用绑定器,则会被破坏(至少在Ivy中是这样),它会强制JIT编译器重新编译组件,而JIT编译器无法这样做,因为它不知道模板/样式文件在哪里。
component.isOwner = false;
fixture.changeDetectorRef.markForCheck();
fixture.detectChanges();