我想测试ngOnInit在组件中调用的subscribe方法。此方法称为getPagesJson,在getjsonService中定义,并从JSON文件中获取一个值。
我的测试目标-使用存根为getPagesJson赋一些值,并将其通过测试过程与原始数据进行比较。
订阅单元测试不起作用。 下面的代码:
first-block.component.ts
import { Component, OnInit } from '@angular/core';
import { GetJsonService } from '../../services/get-json.service';
@Component({
selector: 'app-first-block',
template: '<h1 class="page-title">{{h1}}</h1>',
styleUrls: ['./first-block.component.css']
})
export class FirstBlockComponent implements OnInit {
h1:any;
constructor(private getjsonService: GetJsonService) { }
ngOnInit() {
this.getjsonService.getPagesJson()
.subscribe(
data => this.h1=data["index"][0]["h1"],
error => console.log(error)
);
}
}
get-json.service.ts
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { HttpErrorResponse } from '@angular/common/http';
import { throwError } from 'rxjs';
import { catchError, retry } from 'rxjs/operators';
import { PagesInt } from '../interfaces/pages-int';
@Injectable({
providedIn: 'root'
})
export class GetJsonService {
// Error handler
private handleError(error: HttpErrorResponse) {
if (error.error instanceof ErrorEvent) {
console.error('Error message:', error.error.message);
} else {
console.error(
`Code from backend ${error.status}, ` +
`Error: ${error.error}`);
}
return throwError(
'Something is wrong');
};
constructor(private http: HttpClient) { }
getPagesJson() {
return this.http.get<PagesInt>('/assets/from-server/pages.json')
.pipe(
retry(3),
catchError(this.handleError)
);
}
}
pages-int.ts
export interface PagesInt {
h1:string;
videoUrl?:string;
}
first-block.component.spec.ts
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { of, Observable } from "rxjs";
import { FirstBlockComponent } from './first-block.component';
import { GetJsonService } from '../../services/get-json.service';
describe('FirstBlockComponent', () => {
let component: FirstBlockComponent;
let fixture: ComponentFixture<FirstBlockComponent>;
let spy: jasmine.Spy;
let getjson: GetJsonService;
const getJsonStub = {
getPagesJson() {
const data = [{h1: 'H1 with "Value"'}];
return of( data );
}
};
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ FirstBlockComponent ],
providers: [
{ provide: GetJsonService, useValue: getJsonStub }
]
})
.compileComponents();
getjson = TestBed.get(GetJsonService);
}));
beforeEach(() => {
fixture = TestBed.createComponent(FirstBlockComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
// Errors:
// Uncaught TypeError: Cannot read property '0' of undefined thrown
it('should called getPagesJson', async(() => {
spy = spyOn(getjson, 'getPagesJson');
fixture.detectChanges();
fixture.whenStable().then(() => {
expect(spy).toBeTruthy();
});
}));
// Errors:
// Failed: Cannot read property '0' of undefined
// I'm using very simple and non asynchronous approach below
it('should get H1 by getJsonService.getPagesJson()', () => {
getjson.getPagesJson();
fixture.detectChanges();
expect(component.h1).toBe('H1 with "Value"');
});
// Errors:
// Uncaught TypeError: Cannot read property '0' of undefined thrown
// Expected undefined to be 'H1 with "Value"'.
});
答案 0 :(得分:0)
测试告诉您出了点问题,这是件好事。您评论中的错误告诉您问题的确切原因。
Cannot read property '0' of undefined
表示找不到0
未定义。因此,这部分失败了:data["index"][0]
,并且如果在未定义上找不到0
,则data["index"]
必须为undefined
。
在first-block.component.ts
内,订阅设置了this.h1=data["index"][0]["h1"]
,然后您在测试中将其嘲笑为const data = [{h1: 'H1 with "Value"'}];
。这些不匹配。相反,您应该在测试const data = {index: [{h1: 'H1 with "Value"'}]};
内部-这是一个为数据模型创建接口的好机会,因为您遇到了问题。