Angular 4:Jasmine:Failed:Uncaught(in promise):TypeError:无法读取属性'nativeElement'的null

问题描述 投票:6回答:2

我正在使用角度4 app中的jasmine编写单元测试用例。我每次都得到'无法读取属性'nativeElement'的'null',我不知道为什么。我在下面尝试做的是检查按钮是否被点击。以下是我的代码文件。


spec文件

import { Http, Response, RequestOptions, Request, ConnectionBackend } from '@angular/http';
import { DataShareService } from '../core/services/data-share.service';
import { scooterRepairService } from './services/scooterRepair.service';
import { Router } from '@angular/router';

import { scooterRepairUnitComponent } from './scooter-repair-Unit.component';
import { TestBed, ComponentFixture, async, inject } from '@angular/core/testing';
import { By } from '@angular/platform-browser';
import { DebugElement, NO_ERRORS_SCHEMA } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { SelectItem, CheckboxModule, CalendarModule, MultiSelectModule } from 'primeng/primeng';
import { CoreUIModule } from 'core-ui';
import { RouterTestingModule } from '@angular/router/testing';


describe('scooterRepairUnitComponent', () => {
    let fixture: ComponentFixture<scooterRepairUnitComponent>;
    let component: any;
    let http: Http;
    let dataShare: DataShareService;
    let scooterRepairService: scooterRepairService;
    let router: Router
    let comp = new scooterRepairUnitComponent(http, dataShare, scooterRepairService, router);

    // service stubs to mock services
    let MockResponse = {
        navigate: jasmine.createSpy('Response')
    }

    let MockRequestOptions = {
        navigate: jasmine.createSpy('RequestOptions')
    }

    let MockRequest = {
        navigate: jasmine.createSpy('Request')
    }

    let MockConnectionBackend = {
        navigate: jasmine.createSpy('ConnectionBackend')
    }

    // async beforeEach
    beforeEach(async(() => {

        TestBed.configureTestingModule({
            declarations: [scooterRepairUnitComponent], // declare the test component
            imports: [FormsModule, CheckboxModule, CalendarModule, MultiSelectModule, CoreUIModule, RouterTestingModule],
            schemas: [NO_ERRORS_SCHEMA],
            providers: [Http,
                { provide: Response, useValue: MockResponse },
                { provide: RequestOptions, useValue: MockRequestOptions },
                { provide: Request, useValue: MockRequest },
                { provide: ConnectionBackend, useValue: MockConnectionBackend },
                DataShareService,
                scooterRepairService]

        })
            .compileComponents();  // compile template and css
        fixture = TestBed.createComponent(scooterRepairUnitComponent);
        component = fixture.componentInstance;
    }));



    // synchronous beforeEach -- used if component is having external templates
    beforeEach(() => {

        comp = new scooterRepairUnitComponent(http, dataShare, scooterRepairService, router);
    });   



    it('should', async(() => {
        spyOn(component, 'onClearClick');
         let de: DebugElement = fixture.debugElement.query(By.css('#clearSearch'));
         let el: HTMLElement = de.nativeElement;
        fixture.whenStable().then(() => {


            fixture.detectChanges();
            expect(component.onClearClick).toHaveBeenCalled();
        })
    }));

component.ts

import { Component, OnInit, ViewEncapsulation, ElementRef, Output, Input } from '@angular/core';
import { Pipe, PipeTransform, Inject } from '@angular/core';
import { Http, Response, RequestOptions, Request, ConnectionBackend } from '@angular/http';
import { IScooter } from './models/Scooter';
import { IShop } from './models/shop';
import { ISelectedTab } from './models/selectedTab';
import { RestClientService, EnvironmentService } from 'core-shared/core.service';
import { Observable } from 'rxjs/Observable';
import { DataShareService } from '../core/services/data-share.service';
//mport { CommonService } from '../shared/services/common.service';
import { NgForm, FormBuilder, Validators } from '@angular/forms';
import { Router } from '@angular/router';
import { SelectItem } from 'primeng/primeng';
import { ScooterRepairService } from './services/ScooterRepair.service';


@Component({
    selector: 'Scooter-repair-Unit',
    templateUrl: './Scooter-repair-Unit.component.html',
    styleUrls: ['./Scooter-repair-Unit.component.scss'],
    encapsulation: ViewEncapsulation.None,
})

export class ScooterRepairUnitComponent {
    selectedTab: string = 'ScooterRepair';
    showRepairUnitSelection: boolean=true;
    showScooterRepairUnit:boolean=true;

    showShopRepairUnit:boolean=false ;
    showMissingRepairUnit:boolean=false;
    showAddScooterRepairUnit:boolean=false;
    showAddShopRepairUnit: boolean = false;
    showScooterRepairUnitResultGrid = false;

    ScooterRepairUnitSearchTitle= 'Search Scooter Repair Unit Threshold';
    ScooterRepairUnitSearchResult= 'Scooter Repair Unit Results';
    shopRepairUnitSearchTitle= 'Search Shop Repair Unit Threshold';
    shopRepairUnitSearchResult= 'Shop Repair Unit Results';
    missingRepairUnitSearchResult= 'Missing Repair Unit Results';
    updateRepairUnitTitle= 'Update Results';
    gridPageSize: number;

    Scooters: IScooter[];

    errorMessage: string;

    ScooterRepairs: IScooter[] = [];
    canSubmitAuditRequest = false;
    totalScooterRepairRecords: number;
    isValidated: boolean;
    isSubmittedSuccessfully: boolean;
    clearScooterRepairSearch: boolean;

    constructor(private http: Http,
        private dataShare: DataShareService,
      //  private commonService: CommonService,
        private ScooterRepairService: ScooterRepairService,
       // private loggerService: LoggerService,
       // private storageService: StorageService,
        private router: Router) {
        this.gridPageSize = 10;
    }
     onSelectionChange(tabname) {
        this.SetTab(tabname);
     }


  private SetTab(tabname: string){
    this.showScooterRepairUnit = false;
         this.showShopRepairUnit = false ;
         this.showMissingRepairUnit = false;
     if (tabname === 'ScooterRepair') {
         this.showScooterRepairUnit = true;
     }

     if (tabname === 'shopRepair') {
         this.showShopRepairUnit = true ;
    }
    if (tabname === 'missingRepair') {
         this.showMissingRepairUnit = true;
      }
}

   ngOnInit(): void {
        this.setBreadCrumb();
        this.setLastSearch();
        this.selectedTab = 'ScooterRepair';
    }

   private setBreadCrumb() {
        // Setting Page title
        this.dataShare.setData('appTitle', 'Repair Unit Maintenance');

        // Setting Breadcrumb
        this.dataShare.setData('breadcrumbItems', [
        { label: 'Business Rule Engine' },
        { label: 'Repair Unit Maintenance', url: '/cra' }
    ]);
    }


    onClearClick()
    {
        this.clearScooterRepairSearch = true;
    }

}

HTML文件

<div class="col-lg-12 col-md-12 col-sm-12 col-xs-12" *ngIf="showRepairUnitSelection">
    <div class="panel ">
<form class="form-horizontal scooterUnitSearchForm" #requestauditsearchform="ngForm" action="#" >

                <div class="form-group ">  
                    <div class="col-lg-12 col-xs-12 clearfix">
                    <label for="" class=" col-lg-2 col-xs-6 control-label">
                        Search By:
                    </label>              
                    <label class="control-label radio-inline">
                                <input  type="radio" id="showscooter" name="mainTab" [(ngModel)]="selectedTab" value="scooterRepair" (change)="onSelectionChange(selectedTab)" 
                                 [checked]="selectedTab === scooterRepair">
                                    scooter Repair Unit 
                    </label>
                     <label class=" control-label radio-inline">
                              <input type="radio"  name="mainTab"  id="showShop"  [(ngModel)]="selectedTab" value="shopRepair" (change)="onSelectionChange(selectedTab)" 
                                [checked]="selectedTab === shopRepair"> 
                             Shop  Repair Unit 
                     </label>
                    <label class=" control-label radio-inline">
                              <input type="radio"  name="mainTab"    id="showMissingscooter"  [(ngModel)]="selectedTab" value="missingRepair"(change)="onSelectionChange(selectedTab)" 
                               [checked]="selectedTab === missingRepair"> 
                             Missing scooter Repair Unit
                     </label>

                </div>
                </div>           
</form>
</div>
  </div>

<div class="col-lg-12 col-mg-12 col-sm-12 col-xs-12">
    <collapse-expand-frame 
        [frametitle]="scooterRepairUnitSearchTitle" *ngIf="showscooterRepairUnit">
        <scooter-repair-Unit-search

            (requestscooterRepairSearch)="searchscooterRepairRequest($event)" 
            [clearscooterRepairSearch]="clearscooterRepairSearch"
        >
        </scooter-repair-Unit-search>
    </collapse-expand-frame> 

</div>


<div class="row" style="Margin-bottom:20px" *ngIf="showscooterRepairUnit">
                <div class="col-lg-12 col-md-12 col-sm-12 col-xs-12 ">
                <div class="form-group">
                    <div class="col-lg-12 col-md-12 col-sm-12 col-xs-12 text-sm-right text-md-right text-right">
                    <button pButton type="button" label="Add Repair Unit" (click)="onAddscooterRepair()" class="btn btn-default"></button>
                    <button pButton type="button" label="Search" class="btn btn-default"></button>
                    <button pButton type="button" label="Clear" (click)="onClearClick()" class="btn btn-default"></button>                
                    </div>
                </div>
            </div>
              </div>
<div class="col-lg-12 col-mg-12 col-sm-12 col-xs-12 clearfix"  *ngIf="showAddscooterRepairUnit">


<collapse-expand-frame >
        <add-scooter-repair-Unit

            (requestscooterRepairSearch)="searchscooterRepairRequest($event)" 
        >
        </add-scooter-repair-Unit>
</collapse-expand-frame >

</div>

<div class="col-lg-12 col-mg-12 col-sm-12 col-xs-12">
<collapse-expand-frame 
    [frametitle]="scooterRepairUnitSearchResult" *ngIf="showscooterRepairUnit">
    <scooter-repair-Unit-search-grid 

    >
    </scooter-repair-Unit-search-grid >
</collapse-expand-frame>
</div>

<div class="col-lg-12 col-mg-12 col-sm-12 col-xs-12">
<collapse-expand-frame 
    [frametitle]="updateRepairUnitTitle" *ngIf="showscooterRepairUnit">
    <update-scooter-repair-Unit
    >
    </update-scooter-repair-Unit>
</collapse-expand-frame>
</div>

<div class="col-lg-12 col-mg-12 col-sm-12 col-xs-12">
    <collapse-expand-frame 
        [frametitle]="shopRepairUnitSearchTitle"  *ngIf="showShopRepairUnit">
        <shop-repair-Unit-search
       >
        </shop-repair-Unit-search>

    </collapse-expand-frame> 
</div>



         <div class="row" style="Margin-bottom:20px" *ngIf="showShopRepairUnit">
                <div class="col-lg-12 col-md-12 col-sm-12 col-xs-12 ">
                <div class="form-group">
                    <div class="col-lg-12 col-md-12 col-sm-12 col-xs-12 text-sm-right text-md-right text-right">
                    <button pButton type="button" label="Add Repair Unit" (click)="onAddShopRepair()" class="btn btn-default"></button>
                    <button pButton type="button" label="Search" class="btn btn-default"></button>
                    <button pButton type="button" label="Clear" id="clearSearch" (click)="onClearClick()"  class="btn btn-default"></button>
                    </div>
                </div>
            </div>
              </div>

    <div class="col-lg-12 col-mg-12 col-sm-12 col-xs-12">
    <collapse-expand-frame 
          *ngIf="showAddShopRepairUnit">
        <add-shop-repair-Unit
       >
        </add-shop-repair-Unit>

    </collapse-expand-frame> 
</div>

<div class="col-lg-12 col-mg-12 col-sm-12 col-xs-12">
<collapse-expand-frame 
    [frametitle]="shopRepairUnitSearchResult" *ngIf="showShopRepairUnit">
    <shop-repair-Unit-search-grid 

    >
    </shop-repair-Unit-search-grid >
</collapse-expand-frame>
</div>

<div class="col-lg-12 col-mg-12 col-sm-12 col-xs-12">
<collapse-expand-frame 
    [frametitle]="updateRepairUnitTitle" *ngIf="showShopRepairUnit">
    <update-shop-repair-Unit
    >
    </update-shop-repair-Unit>
</collapse-expand-frame>
</div>
<div class="col-lg-12 col-mg-12 col-sm-12 col-xs-12">
<collapse-expand-frame 
    [frametitle]="missingRepairUnitSearchResult" *ngIf="showMissingRepairUnit">
    <missing-repair-Unit-search-grid 
    >
    </missing-repair-Unit-search-grid>
</collapse-expand-frame>
</div>
angular unit-testing karma-jasmine
2个回答
4
投票

我遇到了同样的问题,我将问题追溯到div上的* ngIf语句

你必须在测试中为'showscooterRepairUnit'设置一个值,否则它将假定为false并将css元素设置为null,导致debugElement为null


0
投票

解决方法

如果您在元素中使用*ngIf,请改用hidden

<h2 [hidden]="hideItem"> My Message</h2>

当jasmine在DOM中找不到该元素时,会导致此错误。最常见的情况是在模板中使用*ngIf。根据docs,* ngIf会破坏DOM中的元素,如果表达式的计算结果为false。


0
投票

我有一个类似的问题,能够通过使用页面对象和querySelectorAll来解决它

fixture.nativeElement.querySelectorAll('button');

HTML:

 <div *ngIf="isAbbreviationsAvailable(element.description); then caseA else caseB"></div>
  <ng-template #caseA>
    <div>

      <ng-template #popContent class="popover">
       <span id="glossary" >  {{element.description| glossary:glossaryDescription}}</span>
          <button class="close" (click)="p.close()"><img src="assets/icons/close.svg"></button>

      </ng-template>

      <button class="popoverLink" [ngbPopover]="popContent" [autoClose]="false"
              triggers="manual" #p="ngbPopover" (click)="p.open()" placement="top-right bottom-right" container="body"
              html="true" >
        {{split(element.description)[0]}}
      </button>

      /{{split(element.description)[1]}}

    </div>
  </ng-template>
  <ng-template #caseB>{{element.description}}</ng-template>

测试用例:

const template: HTMLElement[] = fixture.nativeElement.querySelectorAll('button');
let link: HTMLElement = template[8]

expect(link.textContent.trim()).toEqual('ACC');
© www.soinside.com 2019 - 2024. All rights reserved.