S.G*_*eau 37 unit-testing mocking jasmine typescript angular
假设我有这个
export class QuestionnaireQuestionsComponent {
questions: Question[] = [];
private loading:boolean = true;
constructor(
private route: ActivatedRoute,
public questionnaireService:QuestionnaireService) {}
ngOnInit(){
this.route.parent.params.subscribe((params:any)=>{
this.questionnaireService.getQuestionsForQuestionnaire(params.id).subscribe((questions)=>{
this.questions = questions;
this.loading = false;
});
});
}
}
Run Code Online (Sandbox Code Playgroud)
我的组件实际上工作得很好.问题是我想对它进行单元测试,但我无法弄清楚如何模拟this.route.parent对象.这是我的测试失败了
beforeEach(()=>{
route = new ActivatedRoute();
route.parent.params = Observable.of({id:"testId"});
questionnaireService = jasmine.createSpyObj('QuestionnaireService', ['getQuestionsForQuestionnaire']);
questionnaireService.getQuestionsForQuestionnaire.and.callFake(() => Observable.of(undefined));
component = new QuestionnaireQuestionsComponent(route, questionnaireService);
});
describe("on init", ()=>{
it("must call the service get questions for questionnaire",()=>{
component.ngOnInit();
expect(questionnaireService.getQuestionsForQuestionnaire).toHaveBeenCalled();
});
});
Run Code Online (Sandbox Code Playgroud)
测试因此错误而失败
TypeError: undefined is not an object (evaluating 'this._routerState.parent')
Run Code Online (Sandbox Code Playgroud)
小智 45
使用TestBed
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [YourComponent],
imports: [],
providers: [
{
provide: ActivatedRoute, useValue: {
params: Observable.of({ id: 'test' })
}
}
]
})
.compileComponents();
}));Run Code Online (Sandbox Code Playgroud)
S.G*_*eau 22
AcitvatedRoute是一个根据angular2 docs的接口,所以我所做的是实现一个MockActivatedRoute
import {Observable} from 'rxjs';
import {Type} from '@angular/core';
import {ActivatedRoute,Route,ActivatedRouteSnapshot,UrlSegment,Params,Data } from '@angular/router';
export class MockActivatedRoute implements ActivatedRoute{
snapshot : ActivatedRouteSnapshot;
url : Observable<UrlSegment[]>;
params : Observable<Params>;
queryParams : Observable<Params>;
fragment : Observable<string>;
data : Observable<Data>;
outlet : string;
component : Type<any>|string;
routeConfig : Route;
root : ActivatedRoute;
parent : ActivatedRoute;
firstChild : ActivatedRoute;
children : ActivatedRoute[];
pathFromRoot : ActivatedRoute[];
toString() : string{
return "";
};
}
Run Code Online (Sandbox Code Playgroud)
并ActivatedRoute在我的测试中替换MockActivatedRoute这样的
beforeEach(()=>{
route = new MockActivatedRoute();
route.parent = new MockActivatedRoute();
route.parent.params = Observable.of({id:"testId"});
questionnaireService = jasmine.createSpyObj('QuestionnaireService', ['getQuestionsForQuestionnaire']);
questionnaireService.getQuestionsForQuestionnaire.and.callFake(() => Observable.of(undefined));
component = new QuestionnaireQuestionsComponent(route, questionnaireService);
});
Run Code Online (Sandbox Code Playgroud)
Gar*_*ing 10
对于这个问题的新手,angular.io文档涵盖了这个场景.看到这里
根据上述文件:
创建ActivatedRouteStub要用作测试双精度的类ActivatedRoute
import { ReplaySubject } from 'rxjs/ReplaySubject';
import { convertToParamMap, ParamMap, Params } from '@angular/router';
/**
* An ActivateRoute test double with a `paramMap` observable.
* Use the `setParamMap()` method to add the next `paramMap` value.
*/
export class ActivatedRouteStub {
// Use a ReplaySubject to share previous values with subscribers
// and pump new values into the `paramMap` observable
private subject = new ReplaySubject<ParamMap>();
constructor(initialParams?: Params) {
this.setParamMap(initialParams);
}
/** The mock paramMap observable */
readonly paramMap = this.subject.asObservable();
/** Set the paramMap observables's next value */
setParamMap(params?: Params) {
this.subject.next(convertToParamMap(params));
};
}
Run Code Online (Sandbox Code Playgroud)
然后在测试类中使用stub,如下所示:
activatedRoute.setParamMap({ id: '1234' });
Run Code Online (Sandbox Code Playgroud)
小智 5
要在每个“it”块中自定义模拟的 ActivatedRoute 数据,请结合上面 Kevin Black 的建议
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [YourComponent],
imports: [],
providers: [
{
provide: ActivatedRoute, useValue: {
queryParams: of({ id: 'test' })
}
}
]
})
.compileComponents();
}));Run Code Online (Sandbox Code Playgroud)
在使用fixture.detectChanges() 实例化组件之前,it('') 块中的以下代码
it('test', fakeAsync(() => {
let activatedRoute: ActivatedRoute = fixture.debugElement.injector.get(ActivatedRoute);
activatedRoute.queryParams = of({ firstName: 'john', lastName: 'smith' });
fixture.detectChanges(); // trigger ngOninit()
tick();
}));Run Code Online (Sandbox Code Playgroud)
小智 5
对于从ActivatedRouteSnapshot读取查询参数的场景,例如:
this.someProperty = this.route.snapshot.data.query['paramKey'];
Run Code Online (Sandbox Code Playgroud)
下面的代码将有助于测试将查询参数数据提供给路由
{
provide: ActivatedRoute,
useValue: {
snapshot: {
data: {
query: {
paramKey: 'paramValue'
}
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
34957 次 |
| 最近记录: |