angular 2にコンポーネントがあります。これはルートパラメータの変更に応答します(メインルートから移動しないため、コンポーネントは最初から再読み込みされません。コンポーネントコードは次のとおりです:
_export class MyComponent{
ngOnInit() {
this._routeInfo.params.forEach((params: Params) => {
if (params['area']){
this._pageToShow =params['area'];
}
});
}
}
_
これは機能し、__pageToShow
_はナビゲーションで適切に設定されます。
ルートの変更時の動作をテストしようとしています(つまり、オブザーバブルの2番目のトリガーですが、私のために機能することを拒否しています)。これが私の試みです。
_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();
行なしで実行すると、2番目の期待が失敗するため失敗します。
まず、Subject
の代わりにObservable
を使用する必要があります。オブザーバブルは1回だけサブスクライブされます。そのため、最初のパラメータセットのみを発行します。 Subject
を使用すると、アイテムを放出し続けることができ、単一のサブスクリプションはそれらを取得し続けます。
_let params: Subject<Params>;
beforeEach(() => {
params = new Subject<Params>();
TestBed.configureTestingModule({
providers: [
{ provide: ActivatedRoute, useValue: { params: params }}
]
})
})
_
次に、テストでparams.next(newValue)
を使用して新しい値を出力します。
次に、必ずtick()
を呼び出す必要があります。これがfakeAsync
の仕組みです。非同期タスク解決を制御します。観測可能なのは無秩序なので、イベントを送信した瞬間に、サブスクライバーに同期的に到達しません。したがって、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();
// ...
});