0

我在 Angular v5 上,正在编写浅层组件测试。当 karma 运行测试时,我收到一个错误:

Failed: ExpressionChangedAfterItHasBeenCheckedError: Expression has changed after it was checked. Previous value: 'false'. Current value: 'true'.

Error: ExpressionChangedAfterItHasBeenCheckedError: Expression has changed after it was checked. Previous value: 'false'. Current value: 'true'.
    at viewDebugError (webpack:///./node_modules/@angular/core/esm5/core.js?:9970:32)
    at expressionChangedAfterItHasBeenCheckedError (webpack:///./node_modules/@angular/core/esm5/core.js?:9948:12)
    at checkBindingNoChanges (webpack:///./node_modules/@angular/core/esm5/core.js?:10117:15)
    at checkNoChangesNodeInline (webpack:///./node_modules/@angular/core/esm5/core.js?:14170:9)
    at checkNoChangesNode (webpack:///./node_modules/@angular/core/esm5/core.js?:14142:9)
    at debugCheckNoChangesNode (webpack:///./node_modules/@angular/core/esm5/core.js?:14971:45)
    at debugCheckRenderNodeFn (webpack:///./node_modules/@angular/core/esm5/core.js?:14911:13)
    at Object.eval [as updateRenderer] (ng:///DynamicTestModule/LocationScheduleComponent.ngfactory.js:207:5)
    at Object.debugUpdateRenderer [as updateRenderer] (webpack:///./node_modules/@angular/core/esm5/core.js?:14893:21)
    at checkNoChangesView (webpack:///./node_modules/@angular/core/esm5/core.js?:13982:14)

当我运行应用程序并手动执行测试场景时,不会发生此错误。我确实做了一些调试,我的 html 中的以下行导致了错误:

<i id="save-new-{{i}}" *ngIf="row.get('IsFast').value" class="save_new_icon"

IsFast是一个布尔属性。不知道为什么只有在运行测试时才会导致错误。我只能想象我的测试中有一些东西没有正确设置,因为当我运行应用程序时我没有收到任何错误。

我是一个团队的一员,并试图让我们开始测试我们的 Angular 代码。在我的测试中我需要做些什么来完成这项工作吗?在组件中添加/修改代码只是为了让测试通过,这对我的团队来说是一个很难的卖点,但如果这是让它工作所需要的,那就这样吧。老实说,我觉得我不知道角度测试的某些方面,这就是我收到此错误的原因。

这是我的模板的相关部分:

<ng-container formArrayName="cars" *ngFor="let row of carsFormArray.controls;let i=index;">
                          <tr id="{{i}}">
                            <ng-container [formGroupName]="i">
                              <td>
                                <i id="save-new-{{i}}" *ngIf="row.get('IsFast').value" class="save_new_icon"
                                 aria-hidden="true" [class.disabled-icon]="isDisabled"
                                  (click)="onSaveCarClicked(row)"></i>
                                <i class="delete" *ngIf="ableToDelete()" (click)="onDeleteClicked(row)" aria-hidden="true" [class.disabled-icon]="isDisabled"></i>
                              </td>
                            </ng-container>
                          </tr>
</ng-container>

这是我的测试代码:

import {FastCarComponent} from "./fast-car.component";
import {async, ComponentFixture, TestBed, fakeAsync, tick, flush, discardPeriodicTasks} from "@angular/core/testing";
import {FormsModule, ReactiveFormsModule} from "@angular/forms";
import {DebugElement, NO_ERRORS_SCHEMA} from "@angular/core";
import {Observable} from "rxjs/Rx";
import {Region} from "../core/models/master/region.model";
import {MockActivatedRoute} from "../../testing/mock-activated-route";
import {By} from "@angular/platform-browser";
import {forEach} from "@angular/router/src/utils/collection";
import {click} from "../../testing";
import {DatePickerAdapter, DatePickerComponent} from "../core/components";
import {CoreModule} from "../core/core.module";

describe('FastCarComponent', () => {
...
    beforeEach(async(() => {
      TestBed.configureTestingModule({
        declarations: [ FastCarComponent, DatePickerComponent ],
        imports: [
          NgSelectModule,
          FormsModule,
          ReactiveFormsModule,
        ],
        providers: [
        ...
        ],
        schemas: [NO_ERRORS_SCHEMA]
      })
        .compileComponents();
    }));


    fit('should clear Car Description Validation Error on Adding Fast Car when DisplayFastCar=true and car description validation is satisfied', async(() => {
      fixture = TestBed.createComponent(FastCarComponent);
      component = fixture.componentInstance;
      component.DisplayFastCar = true;
      fixture.detectChanges();  // ngOnInit()
      const page: Page = new Page(fixture);
      click(page.addBtn);
      fixture.detectChanges();
      fixture.whenStable().then(() => {
        let error_span = page.getErrorSpanByTextContent(CAR_DESCRIPTION_ERROR); //get the validation error that shows on page
        if (error_span) {
          carControl = page.getInputByLabelName('Car Description');
          if (carControl) {
            carControl.value = 'Some Description';
            carControl.dispatchEvent(new Event('input'));
          } else {
            fail(`Could not find control with label Car Description`);
          }

        } else {
          fail(`Did Not Find following validation message: ${CAR_DESCRIPTION_ERROR}`);
        }
      });

      fixture.detectChanges(); //run change detection
      fixture.whenStable().then(() => {
        //fixture.detectChanges();
        let error_span = page.getErrorSpanByTextContent(CAR_DESCRIPTION_ERROR);
        expect(error_span).toBeFalsy(`Found Error Span With Text: ${CAR_DESCRIPTION_ERROR}`);
      });
    }));
  });
});
4

0 回答 0