[英]Unit Testing: Angular4: Jasmine: Response is undefined in subscribe when control returns from fake service methods
I am mocking a service by creating its mock class in spec file. 我通过在spec文件中创建其模拟类来模拟服务。 In my component there is a function which calls data service. 在我的组件中,有一个调用数据服务的函数。 When spec runs it successfully goes to mock method but does not return the data, ie, content inside observable.of. 当spec运行时,它成功进入了模拟方法,但不返回数据,即observable.of中的内容。 The error I am getting is 'Expected undefined to be truthy.' 我收到的错误是“预期未定义是真实的”。 for my it case. 对于我的情况。
spec file 规格文件
import { BaseRequestOptions, Http, HttpModule, Response, ResponseOptions } from '@angular/http';
import { MockBackend } from '@angular/http/testing';
import { AddserviceCenterRepairAuthorityComponent } from './add-serviceCenter-repair-authority.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, MultiSelectModule, CalendarModule } from 'primeng/primeng';
import { CoreUIModule } from 'core-ui';
import { RouterTestingModule } from '@angular/router/testing';
import { Router } from '@angular/router';
import { scooterRepairService } from '../services/scooterRepair.service';
import { StorageService } from 'core-shared/core.service';
import { serviceCenterRepairAdd } from '../models/serviceCenter-repair-add.model';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { Observable } from 'rxjs/Observable';
import { IMissingscooterRepair } from '../models/missing-scooter-repair';
import { serviceCenterRepairRecord } from '../models/serviceCenter-repair-record.model';
import { RepairClass } from '../models/repairClass.model';
import { RepairCode } from '../models/repairCode.model';
import { serviceCenterRepairSearch } from '../models/serviceCenter-repair-search.model';
import { scooterRepairSearch } from '../models/scooter-repair-search.model';
import { scooterRepairRecord } from '../models/scooter-repair-record.model';
fdescribe('AddserviceCenterRepairAuthorityComponent', () => {
let fixture: ComponentFixture<AddserviceCenterRepairAuthorityComponent>;
let de: DebugElement;
let el: HTMLElement;
let router: Router;
let comp: AddserviceCenterRepairAuthorityComponent;
class MockscooterRepairService {
headers: Headers = new Headers();
private help = '';
private scooterRepairAuthorityApiurl = 'http://localhost:3000/scooterRepairAuthority';
constructor() {
this.headers.append('appuser', 'devnxd');
}
public submitserviceCenterRepair(serviceCenterRepairAddRecord): Observable<any> {
if (serviceCenterRepairAddRecord.hasOwnProperty()) {
return Observable.throw('Error occurred, please try again');
} else {
return Observable.of(
{
'isSuccess': true, 'results': [{ 'recordId': 1 }], 'recordId': 1
});
}
}
clone(object: any) {
return JSON.parse(JSON.stringify(object));
}
public getscooterInitials(): Observable<SelectItem[]> {
return Observable.of(
{
});
}
public getThresholdValues(isAmountOnly: boolean): Observable<SelectItem[]> {
return Observable.of(
{
});
}
public getRepairClassItems(): Observable<SelectItem[]> {
return Observable.of(
{
});
}
public getRepairCodeItems(): Observable<SelectItem[]> {
return Observable.of(
{
});
}
public getPercentageApprovalItems(): Observable<SelectItem[]> {
return Observable.of(
{
});
}
public getUnitCountItems(scooterInitials: string[]): Observable<SelectItem[]> {
return Observable.of(
{
});
}
public getscooterClassItems(scooterInitials: string[]): Observable<SelectItem[]> {
return Observable.of(
{
});
}
public getFacilityItems(): Observable<SelectItem[]> {
return Observable.of(
{
});
}
public searchscooterRepairs(scooterRepairSearch: scooterRepairSearch): Observable<scooterRepairRecord[]> {
return Observable.of(
{
});
}
public searchserviceCenterRepairs(strFacility: string[], strStatusCode: string[], strthreshold: string[], lastUpdatedDate: Date,
insertDate: Date, effectiveStartDate: Date, effectiveEndDate: Date) {
return Observable.of(
{
});
}
public submitscooterRepair(scooterRepairRecord: scooterRepairRecord, isValidated: boolean = true): Observable<any> {
return Observable.of(
{
});
}
public searchMissingscooterRepairs(): Observable<IMissingscooterRepair> {
return Observable.of(
{
});
}
private getDefaultHeaders(): Headers {
const headers: Headers = new Headers();
// headers.append('appuser', this.auth.user.userName);
headers.append('appuser', 'devvws');
headers.append('Content-Type', 'application/json');
// headers.append('Cache-Control', 'no-cache');
// headers.append('Pragma', 'no-cache');
return headers;
}
private handleError(error: Response) {
return Observable.throw(error.statusText || 'Server error');
}
private extractData(res: Response, isResultOnly: boolean = true) {
const data = res.json();
console.log(data);
// const data = res.json(); // This will be used when actual service calling
if (data.isSuccess) {
return isResultOnly ? data.results : data;
} else if (data.isException && data.errors.length > 0) {
this.handleError(data.errors[0]);
}
return {};
}
convertFeatureListToNGPrimeDropdownOptions(list: any, labelKey, valueKey): SelectItem[] {
const data = this.clone(list);
const options: SelectItem[] = [];
for (let i = 0; i < data.length; i++) {
this.changeKeyName(data[i], labelKey, 'label');
this.changeKeyName(data[i], valueKey, 'value');
options.push(data[i]);
}
return options;
}
private changeKeyName(obj: any, oldKey: string, newKey: string): any {
if (obj.hasOwnProperty(oldKey)) {
obj[newKey] = obj[oldKey];
delete obj[oldKey];
}
return obj;
}
}
// async beforeEach
beforeEach(async(() => {
class RouterStub {
navigateByUrl(url: string) { return url; }
}
TestBed.configureTestingModule({
declarations: [AddserviceCenterRepairAuthorityComponent], // declare the test component
schemas: [NO_ERRORS_SCHEMA],
providers: [scooterRepairService, MockBackend, StorageService,
BaseRequestOptions,
{
provide: Http,
useFactory: (backend, options) => new Http(backend, options),
deps: [MockBackend, BaseRequestOptions]
},
{ provide: scooterRepairService, useClass: MockscooterRepairService },
],
imports: [BrowserAnimationsModule, FormsModule, MultiSelectModule, CalendarModule, CoreUIModule, RouterTestingModule]
})
.compileComponents(); // compile template and css
}));
// synchronous beforeEach -- used if component is having external templates
beforeEach(() => {
fixture = TestBed.createComponent(AddserviceCenterRepairAuthorityComponent);
comp = fixture.componentInstance;
});
it('component is created', () => {
expect(comp).toBeTruthy();
});
xit('unsuccessful should be true when serviceCenterRepairAddRecord is empty object', () => {
comp.serviceCenterRepairAddRecord = <serviceCenterRepairAdd>{};
const recordAddedSuccessfully = comp.onAddserviceCenterRepairClick();
fixture.detectChanges();
expect(recordAddedSuccessfully).toBe(2);
});
it('unsuccessful should be true when serviceCenterRepairAddRecord is not empty object', () => {
comp.serviceCenterRepairAddRecord = <serviceCenterRepairAdd>{
'facilityId': 1, 'statusCode': '200', 'thresholdAmount': 432,
'effectiveStartDate': new Date(), 'effectiveEndDate': new Date(), 'builtEndDate': new Date()
};
comp.unsuccessful = 0;
const recordAddedSuccessfully = comp.onAddserviceCenterRepairClick();
fixture.detectChanges();
expect(recordAddedSuccessfully).toBeTruthy();
});
xit('on cancel scooter repair click', () => {
const spy = spyOn((<any>comp).router, 'navigateByUrl');
comp.onCancelserviceCenterRepairClick();
fixture.detectChanges();
expect(spy).toHaveBeenCalledWith('cra');
});
});
component.ts component.ts
onAddserviceCenterRepairClick() {
this.scooterRepairService.submitserviceCenterRepair(this.serviceCenterRepairAddRecord).subscribe(
response => this.submitedSuccess = response.recordId
,
error => this.errorMessage = <any>error,
() => {
if (this.submitedSuccess === -1) {
alert('Record cannot be added');
this.unsuccessful = 2;
} else {
this.unsuccessful = 1;
this.router.navigate(['cra'], { queryParams: { from: 'serviceCenterRepairSubmit' } });
}
}
);
}
When control returns from the fake service class it should have the object returned from Observable.of. 当控件从伪造的服务类返回时,它应该具有从Observable.of返回的对象。 But in response variable in above component.ts code is undefined. 但是在上面component.ts中的响应变量中,代码未定义。
Please help..! 请帮忙..!
Your returning an array of objects as per your return type in the method. 您将根据方法中的返回类型返回对象数组 。 But you are returning only one object which caused you this error 但是您只返回一个导致此错误的对象
return Observable.of([{
}]);
Response will always be empty since the original call was done to mock class. 自从对模拟类进行了原始调用以来,响应将始终为空。 For unit test check the value of this.submitedSuccess which is an instance variable. 对于单元测试,请检查this.submitedSuccess的值,它是一个实例变量。 Check if its equal to -1 or 1 sent from the fake Observable. 检查其是否等于从假Observable发送的-1或1。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.