为了测试,我们现在使用创建一个测试模块TestBed https://angular.io/docs/ts/latest/api/core/testing/index/TestBed-class.html。我们可以使用TestBed#configureTestingModule
并将元数据对象传递给它,就像我们传递给@NgModule
beforeEach(() => {
TestBed.configureTestingModule({
imports: [ /* modules to import */ ],
providers: [ /* add providers */ ],
declarations: [ /* components, directives, and pipes */ ]
});
});
对于路由,而不是使用普通的RouterModule
,我们会改为使用RouterTestingModule https://angular.io/docs/ts/latest/api/router/testing/index/RouterTestingModule-class.html。这设置了Router
and Location
,所以你不需要自己。您还可以通过调用将路由传递给它RouterTestingModule.withRoutes(Routes)
TestBed.configureTestingModule({
imports: [
RouterTestingModule.withRoutes([
{ path: 'home', component: DummyComponent }
])
]
})
为了得到Location
and Router
在测试中,同样的事情起作用,就像你的例子一样。
let router, location;
beforeEach(() => {
TestBed...
});
beforeEach(inject([Router, Location], (_router: Router, _location: Location) => {
router = _router;
location = _location;
}));
您还可以根据需要注入每个测试
it('should go home',
async(inject([Router, Location], (router: Router, location: Location) => {
})));
The async
上面的用法就像done
除非我们不需要显式调用done
。在所有异步任务完成后,Angular 实际上会为我们做这件事。
获取提供者的另一种方法是从测试台获得。
let location, router;
beforeEach(() => {
TestBed.configureTestingModule({
imports: [RouterTestingModule.withRoutes([
{ path: 'home', component: DummyComponent }
])],
});
let injector = getTestBed();
location = injector.get(Location);
router = injector.get(Router);
});
这是一个完整的测试,重构您的示例
import { Component } from '@angular/core';
import { Location } from '@angular/common';
import { Router } from '@angular/router';
import { RouterTestingModule } from '@angular/router/testing';
import { fakeAsync, async, inject, TestBed, getTestBed } from '@angular/core/testing';
import { By } from '@angular/platform-browser';
@Component({
template: `
<router-outlet></router-outlet>
`
})
class RoutingComponent { }
@Component({
template: ''
})
class DummyComponent { }
describe('component: RoutingComponent', () => {
let location, router;
beforeEach(() => {
TestBed.configureTestingModule({
imports: [RouterTestingModule.withRoutes([
{ path: 'home', component: DummyComponent }
])],
declarations: [RoutingComponent, DummyComponent]
});
});
beforeEach(inject([Router, Location], (_router: Router, _location: Location) => {
location = _location;
router = _router;
}));
it('should go home', async(() => {
let fixture = TestBed.createComponent(RoutingComponent);
fixture.detectChanges();
router.navigate(['/home']).then(() => {
expect(location.path()).toBe('/home');
console.log('after expect');
});
}));
});
UPDATE
另外,如果您想简单地模拟路由器(这实际上可能是进行单元测试的更好方法),您可以简单地执行以下操作
let routerStub;
beforeEach(() => {
routerStub = {
navigate: jasmine.createSpy('navigate'),
};
TestBed.configureTestingModule({
providers: [ { provide: Router, useValue: routerStub } ],
});
});
在测试中,您要做的就是测试当组件与存根交互时,是否使用正确的参数调用存根
expect(routerStub.navigate).toHaveBeenCalledWith(['/route']);
除非您确实想测试某些路由,否则这可能是首选方法。无需设置任何路由。在单元测试中,如果您使用真实的路由,则会涉及不必要的副作用,这些副作用可能会影响您真正尝试测试的内容,这只是组件的行为。组件的行为就是简单地调用navigate
方法。不需要测试路由器是否工作。 Angular 已经保证了这一点。