有一个Angular的Component的单元测试代码,执行后fixture.detectChanges();
就会报错Error: NG0100: ExpressionChangedAfterItHasBeenCheckedError: Expression has changed after it was checked. Previous value for 'showLoading': 'true'. Current value: 'false'. Find more at https://angular.io/errors/NG0100。
代码是这样的,只是在ngAfterViewInit方法里修改了showLoading的值。
export class StartComponent implements AfterViewInit {
showLoading = true;
ngAfterViewInit(): void {
this.showLoading = false;
}
}
UT的代码是这样的:
describe('StartComponent', () => {
let component: StartComponent;
let fixture: ComponentFixture<StartComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [StartComponent]
})
.compileComponents();
});
beforeEach(() => {
fixture = TestBed.createComponent(StartComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
ExpressionChangedAfterItHasBeenCheckedError 错误通常发生在 Angular 的变更检测周期中,它表明在变更检测期间,某些表达式的值已经被修改,这与预期不符合。
在的情况下,fixture.detectChanges() 触发了变更检测,但在变更检测期间,某些属性(如 showLoading)的值发生了变化。由于 Angular 在变更检测期间检测到了这个不一致,因此抛出了 ExpressionChangedAfterItHasBeenCheckedError 错误。
解决这个问题的方法之一是使用 Angular 的生命周期钩子来进行处理。可以使用 ngAfterViewInit() 或 ngAfterContentInit() 钩子来在组件视图初始化完成后再执行的变更操作。这样可以确保在 Angular 完成视图的初始化之后再进行变更操作,避免了在变更检测周期内引起的不一致性。
另外,还可以使用 setTimeout() 来将变更操作推迟到下一个 JavaScript 事件循环中。这样可以使变更操作在 Angular 的变更检测周期之外进行,从而避免了错误的发生。
总之,避免在变更检测周期内修改属性值是解决这个错误的关键。使用 Angular 的生命周期钩子或将变更操作推迟到下一个 JavaScript 事件循环中是解决这个问题的两种常见方法。