Dưới đây là một giải pháp thay thế đó là một chút dài dòng hơn nhưng cho phép chúng ta sử dụng SpyLocation để kiểm tra những thay đổi lộ trình. Trước tiên, chúng tôi tạo các nhà cung cấp bộ định tuyến thử nghiệm chung.
Router-test-providers.ts
import { ComponentResolver } from '@angular/core';
import { Type } from '@angular/core/src/facade/lang';
import { SpyLocation } from '@angular/common/testing';
import { Location } from '@angular/common';
import { Router, RouterOutletMap } from '@angular/router';
import { RouteSegment } from '@angular/router/src/segments';
import { RouterUrlSerializer, DefaultRouterUrlSerializer } from '@angular/router/src/router_url_serializer';
/**
* this class provides the means of loading the tested component type
*/
export class FakeRootComponentLoader {
constructor(private rootComponentType: Type) {
this.rootComponentType = rootComponentType;
}
public getRootComponentType =() => {
return this.rootComponentType;
}
}
let routerFactory = function (
fakeRootComponentLoader: FakeRootComponentLoader,
componentResolver: ComponentResolver,
urlSerializer: RouterUrlSerializer,
routerOutletMap: RouterOutletMap,
location: Location): Router
{
let fakeRootComponentType = fakeRootComponentLoader.getRootComponentType();
/**
* _rootComponent should not be null, but it is what in angular2 rc.1 code
* so we replicate the behaviour
*/
return new Router(
null,
fakeRootComponentType,
componentResolver,
urlSerializer,
routerOutletMap,
location);
};
export const ROUTER_TEST_PROVIDERS: any[] = [
{provide: RouterUrlSerializer, useClass: DefaultRouterUrlSerializer},
RouterOutletMap,
{provide: Location, useClass: SpyLocation},
{provide: RouteSegment, useFactory: (r) => r.routeTree.root, deps: [Router]},
{
provide: Router,
useFactory: routerFactory,
deps: [FakeRootComponentLoader, ComponentResolver, RouterUrlSerializer, RouterOutletMap, Location]
}
];
Các thử nghiệm hoa nhài tương ứng được cung cấp dưới đây.
navigation.spec.ts
import { Component } from '@angular/core';
import { beforeEach, beforeEachProviders, inject } from '@angular/core/testing';
import { ROUTER_DIRECTIVES, Route, Routes, Router } from '@angular/router';
import { TestComponentBuilder } from '@angular/compiler/testing';
import { Location } from '@angular/common';
import { ROUTER_TEST_PROVIDERS, FakeRootComponentLoader } from './router-test-providers';
/**
* We inject router into the EmptyComponent,
* Due to the way DI works in angular2, if we import the ROUTER_TEST_PROVIDERS,
* and inject the Router, we will get our own implementation of the Router injected.
*/
@Component({selector: 'empty-component', template: `empty`})
@Component({
selector: 'empty-component',
template: `empty`,
directives: [ROUTER_DIRECTIVES]
})
class EmptyComponent {
constructor (private router: Router){ }
public getRouter() {return this.router;}
}
@Component({
selector: 'root-component',
template: `<router-outlet></router-outlet>`,
directives: [ROUTER_DIRECTIVES]
})
@Routes([new Route({path: '/login', component: EmptyComponent})])
class RootComponent { }
describe('navigation',() => {
beforeEachProviders(() => [
{
provide: FakeRootComponentLoader,
useFactory:() => new FakeRootComponentLoader(RootComponent)
},
ROUTER_TEST_PROVIDERS,
EmptyComponent
]);
let location: Location;
let testCb: TestComponentBuilder;
let emptyComp: EmptyComponent;
beforeEach(inject([Location, TestComponentBuilder, EmptyComponent], (loc, tcb, emptyCt) => {
location = loc;
testCb = tcb;
emptyComp = emptyCt;
}));
it('should be defined',() => {
expect(EmptyComponent).toBeDefined();
});
it('Should navigate to login', (done) => {
expect(location.path()).toEqual('');
testCb.createAsync(RootComponent).then(fixture => {
emptyComp.getRouter().navigate(['login']).then(() => {
fixture.detectChanges();
expect(location.path()).toBe('/login');
done();
}).catch(e => done.fail(e));
});
});
});
Có những lúc câu trả lời đơn giản đến mức bạn không thể nhìn thấy nó. ** (facepalm) **. Điều đó thật tuyệt! Giải pháp đơn giản nhưng hiệu quả! Cảm ơn bạn! – hartpdx
Giải pháp tốt, cảm ơn! –