簡體   English   中英

Angular 組件測試錯誤:TypeError 無法讀取未定義的屬性“訂閱”

[英]Angular component test error: TypeError Cannot read property 'subscribe' of undefined

我有一個簡單的單元測試,它是在 Angular 6 組件上使用 karma/jasmine 完成的。 從我收集的復數課程和文檔來看,我似乎正在正確地模擬我的組件所需的服務,但是當調用該方法從模擬服務返回數據時,我收到錯誤消息,指出屬性訂閱未定義。

我的“it”函數是空的,因為一旦在 beforeEach 方法中構造了組件,測試就會失敗。 組件的構造函數調用了我試圖測試的方法。 請在下面查看我的代碼。

 import { TestBed, async, ComponentFixture } from '@angular/core/testing'; import { MainComponent } from './main.component'; import { DataService } from '../services/data.service'; import { of } from 'rxjs'; import { NO_ERRORS_SCHEMA } from "@angular/core"; describe('Should construct MainComponent', () => { let mainComponent: MainComponent; let EMPLOYEES; let fixture: ComponentFixture<MainComponent>; let mockDataService; beforeEach(() => { EMPLOYEES = [ { "PrismEmployeeID": 1, "FirstName": "install2", "LastName": "account", "Initials": "IA ", "NickName": "", "SSN": "", "DateOfBirth": "09/26/2014", "HireDate": "09/26/2014", "OfficePhone": "9043943239", "OfficeFax": "9042246400", "ClassificationID": 133, "ClassificationDescription": "Claims Support US Insurance", "SupervisorID": 32, "DepartmentID": 2, "DepartmentDescription": "Information Technology", "SupervisorName": "Jerry Sutton", "CountryID": 1, "CountryName": "United States" } ]; mockDataService = jasmine.createSpyObj(['GetEmployees']); TestBed.configureTestingModule({ declarations: [MainComponent], providers: [{ provide: DataService, useValue: mockDataService }], schemas: [NO_ERRORS_SCHEMA] }); fixture = TestBed.createComponent(MainComponent); fixture.detectChanges(); mockDataService = jasmine.createSpyObj(['GetEmployees']); }); it('should get an array Employees', () => {}); });

主組件

 import { Component, Input, Output, OnInit, EventEmitter } from '@angular/core'; import { DataService } from '../services/data.service'; import { TableComponent } from './table/table.component'; @Component({ selector: 'main', templateUrl: './main.component.html', styleUrls: ['./main.component.css'] }) export class MainComponent { columns: string[] = ['PrismEmployeeID', 'LastName', 'FirstName', 'Initials', 'LastFour', 'BirthDate', 'HireDate', 'OfficePhone', 'OfficeFax', 'ClassificationDescription', 'SupervisorName', 'DepartmentDescription', 'CountryName']; loading: boolean = false; @Input() tableData: Employee[]; constructor(private _dataService: DataService) { this.loadEmployees(); } loadEmployees() { this.loading = true; this._dataService.GetEmployees().subscribe((data) => { this.loading = false; this.tableData = data.json() as Employee[]; }); } onLoading(loading: boolean) { this.loading = loading; } onReloadData(reloadData: boolean) { this.loadEmployees(); } } interface Employee { PrismEmployeeID: number; FirstName: string; LastName: string; Initials: string; NickName: string; SSN: string; DateOfBirth: string; HireDate: string; OfficePhone: string; OfficeFax: string; ClassificationID: number; ClassificationDescription: string; SupervisorID: number; DepartmentID: number; DepartmentDescription: string; SupervisorName: string; CountryID: number; CountryName: string; _selected: boolean; }

 <br/> <h2>Prism Employees</h2> <div *ngIf="loading" class="d-flex justify-content-center bd-highlight mb-3"> <div class="p-2 bd-highlight"></div> <div class="p-2 bd-highlight"> <mat-spinner id="overlay"></mat-spinner> </div> <div class="p-2 bd-highlight"></div> </div> <div *ngIf='tableData'> <table-component #table (loading)="onLoading($event)" (reloadData)="onReloadData($event)" [data]="tableData" [displayedColumns]="columns"></table-component> </div>

問題是您當前提供的服務存根沒有為GetEmployees方法配置返回GetEmployees 這意味着一旦組件調用前一個函數並訂閱其(未定義的)返回,它將觸發異常。

要解決這個問題,您需要偽造該方法的返回值。 基於此答案,您可以按如下方式嘗試:

import {of} from 'rxjs';
...
mockDataService = jasmine.createSpyObj(DataService.Name, {'GetEmployees': of(EMPLOYEES)});
...

更新:

但是,為了使其正常工作,您必須重構您的DataService.GetEmployees方法以具有以下簽名:

GetEmployees(): Observable<Employee[]>;

DataService.GetEmployees的當前實現是一個有漏洞的抽象,因為它從舊的Http API 返回原始Response對象,迫使消費者(在這種情況下是組件)了解有關底層實現的細節(這個細節是data.json() as Employee[]的使用data.json() as Employee[] )

spyOn(mockYourService, 'getSomeData').and.returnValue({ subscribe: () => {} })

你可以......在間諜中返回一個實際的可觀察對象

spyOn(mockYourService, 'getSomeData').and.returnValue(Observable.of(someData)) 也許這比循環訂閱方法更受歡迎,因為如果對服務的調用正在改變組件中的某些東西,這可能是你的東西想要測試

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM