【发布时间】:2018-08-12 06:49:03
【问题描述】:
我如何监视预期会返回诸如 ActivatedRoute.queryParams 之类的 Observable 的存根 Angular Service 方法。这是我失败的规范:
import { TestBed, ComponentFixture } from "@angular/core/testing";
import { RivalChartComponent } from "./rival-chart-component";
import { FormsModule, ReactiveFormsModule } from "@angular/forms";
import { ActivatedRoute, RouterModule, Router } from "@angular/router";
import { appRoutes } from "../app.routes";
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/observable/of';
describe('RivalChartComponent', () => {
let component: RivalChartComponent;
let fixture: ComponentFixture<RivalChartComponent>;
beforeEach(() => {
TestBed.configureTestingModule({
declarations: [
RivalChartComponent
],
imports: [FormsModule, ReactiveFormsModule],
providers: [
{provide: ActivatedRoute, useValue: {queryParams: Observable.of({tags:'all'})}},
{provide: Router, useValue: {}}
]
});
fixture = TestBed.createComponent(RivalChartComponent);
component = fixture.componentInstance;
});
it('should init selectedTags as empty string when no query parameter is set', () => {
spyOn(fixture.debugElement.injector.get(ActivatedRoute), 'queryParams').and.returnValue(Observable.of({tags:null}));
component.ngOnInit();
expect(component.selectedTags.value).toEqual('')
});
});
这里是对应的源代码:
import { Component, OnInit } from '@angular/core';
import { Rival } from '../domain/rival';
import { Route, ActivatedRoute, Router } from '@angular/router';
import { FormGroup, FormControl } from '@angular/forms';
import { CompairValidators } from '../validators/CompairValidators';
@Component({
moduleId: module.id,
selector: 'cp-rival-chart',
templateUrl: 'rival-chart.html'
})
export class RivalChartComponent implements OnInit {
rivals: Array<Rival> = [];
selectedTags: FormControl;
constructor(private route: ActivatedRoute, private router: Router) {
this.selectedTags = new FormControl('', CompairValidators.trimmedArrayMinLengthValidator(3,1));
}
ngOnInit() {
this.updateInputFromQueryParams();
}
updateInputFromQueryParams() {
this.route.queryParams.subscribe((params) => {
this.selectedTags.patchValue(this.createInputTagsFromUrlTags(params.tags));
});
}
createInputTagsFromUrlTags(tags: String): string {
if (!tags) {
return '';
}
const tagsArray = tags.split('+');
const cleanedTags = tagsArray
.filter((tag) => tag && tag.trim());
return '#' + cleanedTags.join(' #');
}
}
该代码预计将从ActivatedRoute 服务给出的名为tags 的查询参数初始化selectedTags FormControl。当没有给出查询参数时,它应该用空字符串初始化 selectedTags。为了测试它,我想监视 ActivatedRoutes.queryParams 方法并为键标签返回一个空字符串,但不幸的是它不起作用。相反,最初传递的 ActivatedRoute 存根的 Observable 被调用,它返回键标签的字符串“全部”。因此,我的测试失败并显示以下消息:
预期 '#all' 等于 ''。
您可能会想,为什么 ActivatedRoute 存根不直接返回空字符串。那是因为我的规范中实际上还有其他测试,我没有在此处添加以专注于我的主要问题。
--- 更新---
原来ActivatedRoute.queryParams 不能在 jasmine 中以常规方式被窥探,因为它不是函数而是属性。解决这个问题的一种方法是提供一个用于注入的对象,其中包含具有所需值的属性queryParams。以下是在我的初始代码中应用的更新,以使测试工作:
let activatedRoute: jasmine.SpyObj<ActivatedRoute>;
beforeEach(() => {
const activatedRouteSpy = {
queryParams: of({ tags: null }),
...jasmine.createSpyObj("ActivatedRoute", [""]),
};
TestBed.configureTestingModule({
declarations: [RivalChartComponent, RivalCardComponent, SortRivalsByVotesPipe, SpinnerComponent],
imports: [FormsModule, ReactiveFormsModule, MatProgressSpinnerModule],
providers: [
{
provide: ActivatedRoute,
useValue: activatedRouteSpy,
},
...
],
});
fixture = TestBed.createComponent(RivalChartComponent);
component = fixture.componentInstance;
activatedRoute = TestBed.get(ActivatedRoute);
});
it("should init selectedTags as empty string when no query parameter is set", () => {
component.ngOnInit();
expect(component.selectedTags.value).toEqual("");
});
【问题讨论】:
-
您也可以添加
RouterTestingModule -
@ErnestoLuis 你会怎么做?您可以提供任何示例或伪代码吗?提醒一下:这里的问题是伪造
ActivatedRoute.queryParams的行为(实际实现),以便参数tags将返回null。