我正在用Jest测试我的Angular应用程序。下面是我的组件的简化模板:
<div *ngIf="viewInitialized">
<button
class="button"
(click)="onLogoutClicked()"
>
{{ changeTokenText }}
</button>
</div>
下面是该组件的简化代码:
@Component({
selector: 'logout-qr-page',
templateUrl: './logout.component.html',
styleUrls: ['./logout.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class LogoutComponent implements OnInit, AfterViewInit {
viewInitialized = false;
constructor(
...
) {}
ngOnInit(): void {
...
}
ngAfterViewInit(): void {
...
this.viewInitialized = true;
}
onLogoutClicked(): void {
...
}
}
我的测试是:
describe('TsdLogoutComponent', () => {
let component: LogoutComponent;
let fixture: ComponentFixture<LogoutComponent>;
let debugElement: DebugElement;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [LogoutComponent],
imports: [
...
],
providers: [
...
],
}).compileComponents();
});
beforeEach(() => {
fixture = TestBed.createComponent(LogoutComponent);
component = fixture.componentInstance;
debugElement = fixture.debugElement;
fixture.detectChanges();
});
it('should create the component', () => {
expect(component).toBeTruthy();
});
it('should correctly render default state', () => {
expect(component.viewInitialized).toBe(true); // PASS
expect(debugElement.query(By.css('.button'))).not.toBeNull(); // FAIL
});
});
所以你可以看到viewInitialized是true,但是没有类为button的元素。调用ViewInit后,它更改了值,但没有更新灯具。
我试过:
- 多次调用
fixture.detectChanges()
,只在测试内部调用(不在每次之前调用),在每次之前和测试中调用; - 使用
await fixture.whenStable()
,与fixture.detectChanges()
一起使用; - 使用
fixture.autoDetectChanges()
。
什么起作用了:如果我手动执行component.viewInitialized = true
(在测试中),如果我在组件中使用信号(viewInitialized = signal(false) => viewInitialized.set(true)
),或者如果我在ngAfterViewInit中调用cdRef.detectChanges()
,则测试开始通过。但我真的不想使用任何这些-在我的项目中,没有信号或cdRef,一切都能完美地工作,我希望它在测试中也能工作,或者至少我想了解这种行为的原因。
1条答案
按热度按时间gojuced71#
我遇到了同样的问题,这个问题最有可能是因为:
显然,使用
OnPush
更改检测,在单元测试中只能调用fixture.detectChanges()
一次。在第一次调用之后,无论您调用fixture.detectChanges()
多少次,视图都不会更新。本文对此进行了解释:https://betterprogramming.pub/how-to-write-tests-for-components-with-onpush-change-detection-in-angular-24f2637a0f40。
您可能需要一个帐户来阅读这篇文章,但其要点是创建一个新函数:
在您的测试中:
也可以用
fakeAsync/tick
的方式使用: