我使用此here:
constructor(private heroService: HeroService,
private activatedRoute: ActivatedRoute) {
}
ngOnInit() {
const heroId = this.activatedRoute.snapshot.paramMap.get('id');
this.heroService.getHeroById(heroId).subscribe((hero: Hero) => {
...
});
}
现在我有一个单元测试需要模拟这个ActivatedRoute。我已经在stackoverflow中检查了一些答案,但没有运气。
请注意,我使用的是snapshot.paramMap ,所以很多解决方案都不起作用。例如,this,this和this不起作用。
我认为近乎有效的答案可能是:
{
provide: ActivatedRoute,
useValue: {paramMap: Observable.of(convertToParamMap({id: 1}))}
}
但也不起作用。
显示的错误是:
Error: Failed to execute 'send' on 'XMLHttpRequest': Failed to load 'ng:///HeroesModule/HeroDetailComponent_Host.ngfactory.js'.
error properties: Object({ INDEX_SIZE_ERR: 1, DOMSTRING_SIZE_ERR: 2, HIERARCHY_REQUEST_ERR: 3, WRONG_DOCUMENT_ERR: 4, INVALID_CHARACTER_ERR: 5, NO_DATA_ALLOWED_ERR: 6, NO_MODIFICATION_ALLOWED_ERR: 7, NOT_FOUND_ERR: 8, NOT_SUPPORTED_ERR: 9, INUSE_ATTRIBUTE_ERR: 10, INVALID_STATE_ERR: 11, SYNTAX_ERR: 12, INVALID_MODIFICATION_ERR: 13, NAMESPACE_ERR: 14, INVALID_ACCESS_ERR: 15, VALIDATION_ERR: 16, TYPE_MISMATCH_ERR: 17, SECURITY_ERR: 18, NETWORK_ERR: 19, ABORT_ERR: 20, URL_MISMATCH_ERR: 21, QUOTA_EXCEEDED_ERR: 22, TIMEOUT_ERR: 23, INVALID_NODE_TYPE_ERR: 24, DATA_CLONE_ERR: 25, code: 19 })
这是因为我正在执行状态为500的响应请求,因为 paramMap未定义,因此请求中没有id。
......任何想法?
谢谢,BR
答案 0 :(得分:5)
将快照添加到useValue,如:
{
provide: ActivatedRoute,
useValue: {
snapshot: {
paramMap: convertToParamMap({
id: '1'
})
}
}
}
答案 1 :(得分:0)
在最新的Angular版本中,默认情况下项目的aot
设置处于启用状态(以便进行更好的编译时类型检查)。如果您的项目就是这种情况,那么您可能至少需要存根出ActivatedRoute和ActivatedRouteSnapshot的所有属性。像这样:
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { Type } from '@angular/core';
import { Location } from '@angular/common';
import { MockPlatformLocation } from '@angular/common/testing';
import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing';
import { ActivatedRoute, ActivatedRouteSnapshot, Params, ParamMap, convertToParamMap } from '@angular/router';
import { of, BehaviorSubject } from 'rxjs';
import { HeroDetailComponent } from './hero-detail.component';
import { Hero } from '../hero';
export class MockActivatedRouteSnapshot implements ActivatedRouteSnapshot {
private innerTestParams?: Params;
constructor(params?: Params) {
if (params) {
this.testParams = params;
} else {
this.testParams = null;
}
}
private get testParams() {
return this.innerTestParams;
}
private set testParams(params: Params) {
this.innerTestParams = params;
}
get paramMap() {
return convertToParamMap(this.testParams);
}
get queryParamMap() {
return this.paramMap;
}
get url() {
return null;
}
get fragment() {
return null;
}
get data() {
return null;
}
get outlet() {
return null;
}
get params() {
return this.innerTestParams;
}
get queryParams() {
return this.innerTestParams;
}
get component() {
return null;
}
get routeConfig() {
return null;
}
get root() {
return null;
}
get parent() {
return null;
}
get firstChild() {
return null;
}
get children() {
return null;
}
get pathFromRoot() {
return null;
}
}
export class MockActivatedRoute implements ActivatedRoute {
private innerTestParams?: Params;
private subject?: BehaviorSubject<Params> = new BehaviorSubject(this.testParams);
private paramMapSubject?: BehaviorSubject<ParamMap> = new BehaviorSubject(convertToParamMap(this.testParams));
constructor(params?: Params) {
if (params) {
this.testParams = params;
} else {
this.testParams = null;
}
}
private get testParams() {
return this.innerTestParams;
}
private set testParams(params: Params) {
this.innerTestParams = params;
this.subject.next(params);
this.paramMapSubject.next(convertToParamMap(params));
}
get snapshot() {
return new MockActivatedRouteSnapshot(this.testParams);
}
get params() {
return this.subject.asObservable();
}
get queryParams() {
return this.params;
}
get paramMap() {
return this.paramMapSubject.asObservable();
}
get queryParamMap() {
return this.paramMap;
}
get url() {
return null;
}
get fragment() {
return null;
}
get data() {
return null;
}
get outlet() {
return null;
}
get component() {
return null;
}
get routeConfig() {
return null;
}
get root() {
return null;
}
get parent() {
return null;
}
get firstChild() {
return null;
}
get children() {
return null;
}
get pathFromRoot() {
return null;
}
}
describe('HeroDetailComponent', () => {
let component: HeroDetailComponent;
let fixture: ComponentFixture<HeroDetailComponent>;
let httpMock: HttpTestingController;
let routeMock: MockActivatedRoute;
let initialMockParams: Params;
let locationMock: MockPlatformLocation;
beforeEach(async(() => {
initialMockParams = {id: 11};
routeMock = new MockActivatedRoute(initialMockParams);
locationMock = new MockPlatformLocation;
TestBed.configureTestingModule({
imports: [
HttpClientTestingModule
],
declarations: [ HeroDetailComponent ],
providers: [
{
provide: ActivatedRoute, useValue: routeMock,
},
{
provide: Location, useValue: locationMock,
}
]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(HeroDetailComponent);
component = fixture.componentInstance;
httpMock = TestBed.inject<HttpTestingController>(HttpTestingController as Type<HttpTestingController>);
fixture.detectChanges();
});
afterEach(() => {
httpMock.verify();
});
it('should be created', () => {
fixture.detectChanges();
expect(component).toBeTruthy();
const dummyHero: Hero = { id: 11, name: 'dummyHero' };
const req = httpMock.expectOne('api/details/11');
req.flush(dummyHero);
});
});