我有一个带有标签的组件。我需要导航到一个选项卡,然后测试可见的输入等。从控制台日志中可以看到,我正在执行的操作正在使用以下过程调用正在监视的函数。我还可以看到这是以正确的顺序发生的。
不幸的是,这会产生成功的测试而没有错误,根据ng test,在测试中没有发现期望。 (SPEC没有期望)
将期望值放置在whenStable命令之外会使期望值在blur命令之前运行。

it('should call to save changes when project name is blurred',
    fakeAsync(() => {
        component.ngOnInit();
        tick();
        const tabLabels = fixture.debugElement.queryAll(By.css('.mat-tab-label'));
        console.log(tabLabels);
        tabLabels[1].triggerEventHandler('click', null);
        fixture.detectChanges();
        fixture.whenStable().then(() => {
            const projectName = fixture.debugElement.query(By.css('#projectName'));
            console.log(projectName);
            let mySpy = spyOn(component, 'saveProject');
            projectName.triggerEventHandler('blur', null);
            console.log('Lowered expectations');
            expect(mySpy).toHaveBeenCalled();
        });
    })
);
这是与测试关联的HTML。
    <!-- HEADER -->
    <div class="header accent" fxLayout="row"></div>
    <!-- / HEADER -->

    <!-- CONTENT -->
    <div class="content">


        <!-- CENTER -->
        <div class="center p-24" fusePerfectScrollbar>

            <!-- CONTENT -->
            <div class="content p-24" style="box-shadow:0px 0px 0px rgba(0,0,0,0) !important;">

                <mat-tab-group fxFlex="80%"
                               style="margin:0px 10%">

                    <mat-tab id="projectSelectionTab" label="Project Selection">


                        <div fxFlex="80%"
                             fxLayout="column"
                             style="margin:0px 10%"
                             *ngIf="versionList && projectList">

                            <h1 class="mt-32 mb-20">Select a Project</h1>

                            <mat-divider></mat-divider>


                            <div *ngIf="projectList.length==0">
                                You currently have no designs. Go to the marketplace and select a design to add to your list of projects.
                            </div>

                            <table class="displayTable">


                                <tr (click)="setCurrentProject( project ) "
                                   target="_blank"
                                   class="projectRow"
                                   [ngClass]="{'currentItem' : project==currentProject}"
                                   *ngFor="let project of projectList">

                                    <td class="mat-subheading-2"
                                        style="width:10%">
                                        <mat-icon style="cursor:pointer"
                                                  matTooltip="Open in design studio"
                                                  [routerLink]="['/designStudio/project/'+project.uid]">
                                            color_lens
                                        </mat-icon>

                                        <mat-icon style="cursor:pointer"
                                                  matTooltip="View Quotes for this project"
                                                  [routerLink]="['/invoice/'+versionList[versionList.length-1]['uid']]">
                                            attach_money
                                        </mat-icon>
                                    </td>

                                    <td class="mat-subheading-2"
                                        style="width:25%">
                                            {{ project.name }}
                                    </td>


                                    <td class="mat-subheading-2"
                                        style="width:20%">
                                            {{ project.dateCreated | date:'short' }}
                                    </td>


                                    <td class="mat-body-1" >

                                        <span style="font-weight:bold; margin-right:10px;">Type : {{project.designType}}</span>
                                        <span style="font-weight:bold; margin-right:10px;">Versions : {{project.versions.length}}</span>
                                        {{ project.description }}
                                    </td>

                                </tr>


                            </table>

                        </div>

                    </mat-tab>


                    <mat-tab id="projectDataTab" label="Project Data" flex="100%">

                        <div flex="100%"
                             layout="column"
                             style="width:100%"
                             *ngIf="currentProject.uid">

                            <h2 class="mt-32 mb-20">
                                Project Data -
                                    <mat-icon style="cursor:pointer"
                                              matTooltip="Open in design studio"
                                              [routerLink]="['/designStudio/project/'+currentProject.uid]">
                                        color_lens
                                    </mat-icon>

                            </h2>


                            <!-- TOP ROW OF PROJECT DATA -->
                            <div fxLayout="row" fxLayoutAlign="center" flex="100%">

                                <div fxFlex="50%"fxLayout="column" class="text-center">
                                    <mat-form-field appearance="outline" floatLabel="always" class="w-100-p">
                                        <mat-label>Project Name</mat-label>
                                        <input matInput
                                               id="projectName"
                                               class="form-control"
                                               placeholder="Product Name"
                                               name="projectName"
                                               #projectName="ngModel"
                                               [(ngModel)]="currentProject['name']"
                                               (blur)="saveProject()"
                                               minlength="5"
                                               maxlength="150"
                                               required>
                                    </mat-form-field>

                                    <div [hidden]="projectName.valid || projectName.pristine || !projectName.errors?.minlength"
                                         class="alert alert-danger">
                                        Project name is required with at least 5 characters
                                    </div>


                                    <mat-form-field style="min-height:190px" appearance="outline" floatLabel="always" class="w-100-p">
                                        <mat-label>Project Description</mat-label>
                                        <textarea style="min-height:190px"
                                                  matInput
                                                  id="projectDescription"
                                                  placeholder="Product Description"
                                                  name="description"
                                                  #projectDescription="ngModel"
                                                  [(ngModel)]="currentProject['description']"
                                                  (blur)="saveProject()"
                                                  rows="5"
                                                  required
                                                  minlength="25">
                                        </textarea>
                                    </mat-form-field>

                                    <div [hidden]="projectDescription.valid || projectDescription.pristine || !projectDescription.errors?.minlength"
                                         class="alert alert-danger">
                                        Project description is required with at least 25 characters
                                    </div>


                                </div>


                                <div fxFlex="50" fxLayout="column" fxLayoutAlign="center center">

                                    <div fxFlex="80" style="margin:0px 10%">
                                        <img [src]="(designImageUrl | async)">
                                    </div>


                                    <div fxLayout="row"
                                         fxLayoutAlign="center"
                                         class="w-80-p">
                                        <button mat-raised-button
                                                color="primary"
                                                *ngIf="changesExist"
                                                (click)="saveProject(); changesExist=false;"
                                                style="margin:10px 25%; width:50%">
                                            Save Project Changes
                                        </button>
                                    </div>

                                </div>

                            </div>

                        </div>
                        <!-- / TOP ROW OF PROJECT DATA -->

                    </mat-tab>









                    <mat-tab id="versionDataTab" label="Version Data">


                        <div layout="column"
                             flex="100%"
                             style="width:100%"
                             *ngIf="currentProject !== undefined">

                            <h2 class="mt-32 mb-20">Version Data</h2>



                            <!-- Row showing button to create default version -->
                            <div fxLayout="row"
                                 fxLayoutAlign="center center"
                                 flex="100%">

                                <div fxFlex="20" style="margin:20px 5%">
                                    <button mat-stroked-button
                                            color="accent"
                                            (click)="createNewVersion('default')">
                                        New version (default)
                                    </button>
                                </div>

                            </div>


                            <!-- Row showing the version list -->
                            <div fxLayout="row" fxLayoutAlign="center" flex="100%">

                                <table class="displayTable"
                                       fxFlex="60" style="margin:0px 5%">
                                    <thead>
                                        <tr>
                                            <th>VERSION NUMBER AND NAME</th>
                                            <th></th>
                                        </tr>
                                    </thead>
                                    <tbody>
                                        <tr *ngFor="let version of versionList; index as j"
                                            class="projectRow"
                                            [ngClass]="{'currentItem' : version==currentVersion}"
                                            (click)="onVersionSelected( j )">
                                            <td>{{j+1}} - {{version.name}}</td>
                                            <td>
                                                <mat-icon style="cursor:pointer"
                                                          matTooltip="View Quotes for this version"
                                                          [routerLink]="['/invoice/'+version['uid']]">
                                                    attach_money
                                                </mat-icon>
                                                <mat-icon style="cursor:pointer"
                                                          matTooltip="Make copy as latest version"
                                                          (click)="createNewVersion( j )">
                                                    add_circle
                                                </mat-icon>
                                            </td>
                                        </tr>
                                    </tbody>
                                </table>

                                <!--

                                <div fxFlex="40" style="margin:0px 5%">
                                    <mat-form-field class="w-100-p ml-10-p mt-20 form-group">
                                      <mat-label>Select a version to see the details</mat-label>
                                      <mat-select  (selectionChange)="onVersionSelected(versionIndex)"
                                                   name="versionIndex"
                                                   #name="ngModel"
                                                   [(ngModel)]="versionIndex">
                                        <mat-option *ngFor="let version of versionList; index as i" [value]="i">
                                          {{i+1}} - {{version.name}}
                                        </mat-option>
                                      </mat-select>
                                    </mat-form-field>
                                </div>



                                <div fxLayoutAlign="center center" fxFlex="40" style="margin:0px 5%">
                                    <button mat-button class="red-900 mt-8" *ngIf="currentVersion.latest">Submit for purchase</button>
                                    <button mat-button class="primary mt-8" *ngIf="!currentVersion.latest">Recreate as latest version</button>
                                </div>

                            -->


                            </div>


                            <div fxLayout="row" fxLayoutAlign="center" flex="100%">

                                <!-- VERSIONS DATA -->
                                <div fxLayout="column"
                                     class="mt-32"
                                     flex="45%"
                                     style="width:40%; margin:0px 5%">

                                    <h3>Data</h3>

                                    <div fxLayout="row"
                                         class="mt-20 mb-32">
                                        <div fxFlex="50">
                                            Estimated price - {{currentVersion.price}}
                                        </div>
                                        <div fxFlex="50">
                                            Date Created - {{currentVersion.dateCreated | date:'short'}}
                                        </div>
                                    </div>


                                    <mat-form-field appearance="outline"
                                                    floatLabel="always"
                                                    class="w-100-p">
                                        <mat-label>Version Name</mat-label>
                                        <input matInput
                                               class="form-control"
                                               placeholder="Version Name"
                                               name="vName"
                                               #versionName="ngModel"
                                               (blur)="versionChangesExist=true"
                                               [(ngModel)]="currentVersion.name"
                                               required
                                               minlength="5"
                                               maxlength="150">
                                    </mat-form-field>

                                    <div [hidden]="versionName.valid || versionName.pristine || !versionName.errors?.minlength"
                                         class="alert alert-danger">
                                        Version name is required with at least 5 characters
                                    </div>


                                    <mat-form-field appearance="outline"
                                                    floatLabel="always"
                                                    class="w-100-p">
                                        <mat-label>Version Description</mat-label>
                                        <textarea matInput
                                                  placeholder="Version Description"
                                                  class="form-control"
                                                  name="versionDescription"
                                                  #versionDescription="ngModel"
                                                  (blur)="versionChangesExist=true"
                                                  [(ngModel)]="currentVersion.description"
                                                  rows="5"
                                                  required>
                                        </textarea>
                                    </mat-form-field>

                                    <div [hidden]="versionDescription.valid || versionDescription.pristine || !versionDescription.errors?.minlength"
                                         class="alert alert-danger">
                                        Version description is required with at least 25 characters
                                    </div>

                                </div>
                                <!--/  VERSION DATA -->



                                <!-- MEASUREMENT LIST -->
                                <div fxLayout="column"
                                     class="mt-32"
                                     flex="45%"
                                     style="width:40%; margin:0px 5%">

                                    <div fxLayout="row" fxLayoutAlign="center" flex="100%">
                                        <button mat-raised-button
                                                color="primary"
                                                *ngIf="versionChangesExist"
                                                (click)="saveVersion(); versionChangesExist=false;"
                                                style="margin:10px 15%; width:70%">
                                            Save Version
                                        </button>
                                    </div>

                                     <h3>Measurements</h3>

                                    <table mat-table [dataSource]="currentVersion.measurements"
                                           class="mat-elevation-z8"
                                           style="box-shadow:none;">

                                      <ng-container matColumnDef="name">
                                        <th mat-header-cell *matHeaderCellDef> Name </th>
                                        <td mat-cell *matCellDef="let meas"> {{meas.name}} </td>
                                      </ng-container>

                                      <ng-container matColumnDef="value">
                                        <th mat-header-cell *matHeaderCellDef> Value </th>
                                        <td mat-cell *matCellDef="let meas"> {{meas.value}} </td>
                                      </ng-container>

                                      <tr mat-header-row *matHeaderRowDef="columnsToDisplayMeas"></tr>
                                      <tr mat-row *matRowDef="let row; columns: columnsToDisplayMeas;"></tr>
                                    </table>

                                </div>
                                <!--/  MEASUREMENT LIST -->

                            </div>

                        </div>

                    </mat-tab>







                    <mat-tab id="designAndPurchaseTab" label="Design and Purchase Status">


                        <div flex="100%"
                             layout="column"
                             style="width:100%"
                             *ngIf="currentProject !== undefined">


                            <h2 class="mt-32 mb-20">Design and Purchase Status</h2>


                            <div fxLayout="row"
                                 fxLayoutAlign="center center">
                                <div *ngFor="let stage of projectStages; index as j;"
                                     fxLayoutAlign="center center"
                                     [class]="projectStatus[j] ? 'arrow_box_green' : 'arrow_box_red' "
                                     [ngStyle]="{'z-index':1000-j}"
                                     (click)="setSelected( j )">
                                    <span>{{stage}}</span>
                                </div>
                            </div>

                            <div fxLayout="row"
                                 fxLayoutAlign="center center">
                                <div *ngFor="let stage of projectStages; index as j;"
                                     fxLayoutAlign="center center">

                                    <div [class]="projectStatus[j] ? 'green_right' : '' "
                                         *ngIf="selectedStatus[j]"></div>

                                    <div [class]="!projectStatus[j] ? 'red_right' : '' "
                                         *ngIf="selectedStatus[j]"></div>

                                    <div *ngIf="!selectedStatus[j]"
                                         class="filler"></div>

                                    <div class="filler"></div>

                                </div>

                            </div>



                            <div fxLayout="row"
                                 fxLayoutAlign="center center">

                                <div *ngFor="let text of stageTexts; index as j;"
                                     fxLayoutAlign="center center">

                                    <div fxFlex="50"
                                         *ngIf="selectedStatus[j] && projectStatus[j]">{{text.done}}</div>

                                    <div fxFlex="50"
                                         *ngIf="selectedStatus[j] && !projectStatus[j]">{{text.notdone}}</div>

                                </div>

                            </div>


                        </div>

                    </mat-tab>






                </mat-tab-group>


            </div>
            <!-- / CONTENT -->

        </div>
        <!-- / CENTER -->

    </div>
    <!-- / CONTENT -->

</div>

最佳答案

这是因为whenStable()fakeAsync()函数中不能很好地与async函数配合使用。

也许像这样更改您的测试用例,应该可以工作。

it('should call to save changes when project name is blurred',
    fakeAsync(() => {
        component.ngOnInit();
        tick();
        const tabLabels = fixture.debugElement.queryAll(By.css('.mat-tab-label'));
        console.log(tabLabels);
        tabLabels[1].triggerEventHandler('click', null);
        fixture.detectChanges();

        flushMicrotasks(); // or alternatively flush() or tick(250);

        fixture.detectChanges();

        const projectName = fixture.debugElement.query(By.css('#projectName'));
        console.log(projectName);
        let mySpy = spyOn(component, 'saveProject');
        projectName.triggerEventHandler('blur', null);
        console.log('Lowered expectations');
        expect(mySpy).toHaveBeenCalled();
    })
);
编辑:

关于angular - Angular Testing -预期是否包含在whenStable中,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/62806027/

10-11 07:18