Angular 2 - 测试路由参数的变化
Angular 2 - test for change in route params
我在 angular2 中有一个组件响应路由参数的变化(该组件不会从头重新加载,因为我们没有离开主路由。这是组件代码:
export class MyComponent{
ngOnInit() {
this._routeInfo.params.forEach((params: Params) => {
if (params['area']){
this._pageToShow =params['area'];
}
});
}
}
这很有用,_pageToShow
设置适合导航。
我正在尝试测试路线更改时的行为(因此可观察到的第二个触发器但它拒绝为我工作。)这是我的尝试:
it('sets PageToShow to new area if params.area is changed', fakeAsync(() => {
let routes : Params[] = [{ 'area': "Terry" }];
TestBed.overrideComponent(MyComponent, {
set: {
providers: [{ provide: ActivatedRoute,
useValue: { 'params': Observable.from(routes)}}]
}
});
let fixture = TestBed.createComponent(MyComponent);
let comp = fixture.componentInstance;
let route: ActivatedRoute = fixture.debugElement.injector.get(ActivatedRoute);
comp.ngOnInit();
expect(comp.PageToShow).toBe("Terry");
routes.splice(2,0,{ 'area': "Billy" });
fixture.detectChanges();
expect(comp.PageToShow).toBe("Billy");
}));
但是当我 运行 它时,这会引发 TypeError: Cannot read property 'subscribe' of undefined
异常。如果我 运行 它没有 fixture.detectChanges();
行,它会失败,因为第二个期望失败。
首先,您应该使用 Subject
而不是 Observable
。 observable 只被订阅一次。所以它只会发出第一组参数。使用 Subject
,您可以不断发射物品,并且单个订阅将不断获得它们。
let params: Subject<Params>;
beforeEach(() => {
params = new Subject<Params>();
TestBed.configureTestingModule({
providers: [
{ provide: ActivatedRoute, useValue: { params: params }}
]
})
})
然后在您的测试中使用 params.next(newValue)
.
发出新值
其次,您需要确保调用tick()
。这就是 fakeAsync
的工作原理。您控制异步任务的解决。由于 observable 是异步的,在我们发送事件的那一刻,它不会同步到达订阅者。所以我们需要用 tick()
强制同步行为
这里是一个完整的测试(Subject
是从'rxjs/Subject'
导入的)
@Component({
selector: 'test',
template: `
`
})
export class TestComponent implements OnInit {
_pageToShow: string;
constructor(private _route: ActivatedRoute) {
}
ngOnInit() {
this._route.params.forEach((params: Params) => {
if (params['area']) {
this._pageToShow = params['area'];
}
});
}
}
describe('TestComponent', () => {
let fixture: ComponentFixture<TestComponent>;
let component: TestComponent;
let params: Subject<Params>;
beforeEach(() => {
params = new Subject<Params>();
TestBed.configureTestingModule({
declarations: [ TestComponent ],
providers: [
{ provide: ActivatedRoute, useValue: { params: params } }
]
});
fixture = TestBed.createComponent(TestComponent);
component = fixture.componentInstance;
});
it('should change on route param change', fakeAsync(() => {
// this calls ngOnInit and we subscribe
fixture.detectChanges();
params.next({ 'area': 'Terry' });
// tick to make sure the async observable resolves
tick();
expect(component._pageToShow).toBe('Terry');
params.next({ 'area': 'Billy' });
tick();
expect(component._pageToShow).toBe('Billy');
}));
});
我更喜欢像这样从 ActivatedRouteSnapshot 获取路由参数和数据 this.route.snapshot.params['type']
如果你用同样的方法,你可以这样测试
1) 在您的测试提供商中
{provide: ActivatedRoute, useValue: {snapshot: { params: { type: '' } }}}
2) 在您的测试规范中
it('should...', () => {
component.route.snapshot.params['type'] = 'test';
fixture.detectChanges();
// ...
});
我在 angular2 中有一个组件响应路由参数的变化(该组件不会从头重新加载,因为我们没有离开主路由。这是组件代码:
export class MyComponent{
ngOnInit() {
this._routeInfo.params.forEach((params: Params) => {
if (params['area']){
this._pageToShow =params['area'];
}
});
}
}
这很有用,_pageToShow
设置适合导航。
我正在尝试测试路线更改时的行为(因此可观察到的第二个触发器但它拒绝为我工作。)这是我的尝试:
it('sets PageToShow to new area if params.area is changed', fakeAsync(() => {
let routes : Params[] = [{ 'area': "Terry" }];
TestBed.overrideComponent(MyComponent, {
set: {
providers: [{ provide: ActivatedRoute,
useValue: { 'params': Observable.from(routes)}}]
}
});
let fixture = TestBed.createComponent(MyComponent);
let comp = fixture.componentInstance;
let route: ActivatedRoute = fixture.debugElement.injector.get(ActivatedRoute);
comp.ngOnInit();
expect(comp.PageToShow).toBe("Terry");
routes.splice(2,0,{ 'area': "Billy" });
fixture.detectChanges();
expect(comp.PageToShow).toBe("Billy");
}));
但是当我 运行 它时,这会引发 TypeError: Cannot read property 'subscribe' of undefined
异常。如果我 运行 它没有 fixture.detectChanges();
行,它会失败,因为第二个期望失败。
首先,您应该使用 Subject
而不是 Observable
。 observable 只被订阅一次。所以它只会发出第一组参数。使用 Subject
,您可以不断发射物品,并且单个订阅将不断获得它们。
let params: Subject<Params>;
beforeEach(() => {
params = new Subject<Params>();
TestBed.configureTestingModule({
providers: [
{ provide: ActivatedRoute, useValue: { params: params }}
]
})
})
然后在您的测试中使用 params.next(newValue)
.
其次,您需要确保调用tick()
。这就是 fakeAsync
的工作原理。您控制异步任务的解决。由于 observable 是异步的,在我们发送事件的那一刻,它不会同步到达订阅者。所以我们需要用 tick()
这里是一个完整的测试(Subject
是从'rxjs/Subject'
导入的)
@Component({
selector: 'test',
template: `
`
})
export class TestComponent implements OnInit {
_pageToShow: string;
constructor(private _route: ActivatedRoute) {
}
ngOnInit() {
this._route.params.forEach((params: Params) => {
if (params['area']) {
this._pageToShow = params['area'];
}
});
}
}
describe('TestComponent', () => {
let fixture: ComponentFixture<TestComponent>;
let component: TestComponent;
let params: Subject<Params>;
beforeEach(() => {
params = new Subject<Params>();
TestBed.configureTestingModule({
declarations: [ TestComponent ],
providers: [
{ provide: ActivatedRoute, useValue: { params: params } }
]
});
fixture = TestBed.createComponent(TestComponent);
component = fixture.componentInstance;
});
it('should change on route param change', fakeAsync(() => {
// this calls ngOnInit and we subscribe
fixture.detectChanges();
params.next({ 'area': 'Terry' });
// tick to make sure the async observable resolves
tick();
expect(component._pageToShow).toBe('Terry');
params.next({ 'area': 'Billy' });
tick();
expect(component._pageToShow).toBe('Billy');
}));
});
我更喜欢像这样从 ActivatedRouteSnapshot 获取路由参数和数据 this.route.snapshot.params['type']
如果你用同样的方法,你可以这样测试
1) 在您的测试提供商中
{provide: ActivatedRoute, useValue: {snapshot: { params: { type: '' } }}}
2) 在您的测试规范中
it('should...', () => {
component.route.snapshot.params['type'] = 'test';
fixture.detectChanges();
// ...
});