Angular 2最终释放路由器单元测试 [英] Angular 2 Final Release Router Unit Test
问题描述
如何使用karma和jasmine对Angular 2.0.0版中的路由器进行单元测试?
How do I unit test routers in Angular version 2.0.0 with karma and jasmine?
以下是我的旧单元测试在2.0.0-beta版中的样子.14
Here's what my old unit test looks like in version 2.0.0-beta.14
import {
it,
inject,
injectAsync,
beforeEach,
beforeEachProviders,
TestComponentBuilder
} from 'angular2/testing';
import { RootRouter } from 'angular2/src/router/router';
import { Location, RouteParams, Router, RouteRegistry, ROUTER_PRIMARY_COMPONENT } from 'angular2/router';
import { SpyLocation } from 'angular2/src/mock/location_mock';
import { provide } from 'angular2/core';
import { App } from './app';
describe('Router', () => {
let location, router;
beforeEachProviders(() => [
RouteRegistry,
provide(Location, {useClass: SpyLocation}),
provide(Router, {useClass: RootRouter}),
provide(ROUTER_PRIMARY_COMPONENT, {useValue: App})
]);
beforeEach(inject([Router, Location], (_router, _location) => {
router = _router;
location = _location;
}));
it('Should be able to navigate to Home', done => {
router.navigate(['Home']).then(() => {
expect(location.path()).toBe('');
done();
}).catch(e => done.fail(e));
});
});
推荐答案
为了测试我们现在使用 TestBed
。我们可以使用 TestBed#configureTestingModule
并将元数据对象传递给它,就像我们传递给 @NgModule
<一样/ p>
For testing we now create a testing module using TestBed
. We can use the TestBed#configureTestingModule
and pass a metadata object to it the same way we would pass to @NgModule
beforeEach(() => {
TestBed.configureTestingModule({
imports: [ /* modules to import */ ],
providers: [ /* add providers */ ],
declarations: [ /* components, directives, and pipes */ ]
});
});
用于路由,而不是使用普通的 RouterModule
,我们将使用 RouterTestingModule
。这将设置路由器
和位置
,因此您不需要自己。您也可以通过调用 RouterTestingModule.withRoutes(路由)
For routing, instead of using the normal RouterModule
, we would instead use RouterTestingModule
. This sets up the Router
and Location
, so you don't need to yourself. You can also pass routes to it, by calling RouterTestingModule.withRoutes(Routes)
TestBed.configureTestingModule({
imports: [
RouterTestingModule.withRoutes([
{ path: 'home', component: DummyComponent }
])
]
})
获取位置
和路由器
在测试中,同样的方法可行,如您的示例所示。
To get the Location
and Router
in the test, the same thing works, as in your example.
let router, location;
beforeEach(() => {
TestBed...
});
beforeEach(inject([Router, Location], (_router: Router, _location: Location) => {
router = _router;
location = _location;
}));
您还可以根据需要注入每个测试
You could also inject into each test as necessary
it('should go home',
async(inject([Router, Location], (router: Router, location: Location) => {
})));
上面的 async
用作 done
除了我们不需要显式调用 done
。所有异步任务完成后,Angular实际上都会为我们做到这一点。
The async
above is used like done
except we don't need to explicitly call done
. Angular will actually do that for us after all asynchronous tasks are complete.
另一种获取提供者的方法是从测试台获得。
Another way to get the providers is from the test bed.
let location, router;
beforeEach(() => {
TestBed.configureTestingModule({
imports: [RouterTestingModule.withRoutes([
{ path: 'home', component: DummyComponent }
])],
});
let injector = getTestBed();
location = injector.get(Location);
router = injector.get(Router);
});
这是一个完整的测试,重构你的例子
Here's a complete test, refactoring your example
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
此外,如果你想要简单地模拟路由器,这实际上可能是进行单元测试的更好方法,你可以简单地做
UPDATE
Also, if you want to simply mock the router, which actually might be the better way to go in a unit test, you could simply do
let routerStub;
beforeEach(() => {
routerStub = {
navigate: jasmine.createSpy('navigate'),
};
TestBed.configureTestingModule({
providers: [ { provide: Router, useValue: routerStub } ],
});
});
在你的测试中,你要做的就是测试使用正确的参数调用存根,当组件与它交互时
And in your tests, all you want to do is test that the stub is called with the correct argument, when the component interacts with it
expect(routerStub.navigate).toHaveBeenCalledWith(['/route']);
除非你真的想测试一些路由,否则这可能是首选方式。无需设置任何路由。在单元测试中,如果您使用实际路由,则会涉及不必要的副作用,这可能会影响您实际尝试测试的内容,这只是组件的行为。组件的行为是简单地调用导航
方法。它不需要测试路由器的工作原理。 Angular已经保证了。
Unless you actually want to test some routing, this is probably the preferred way to go. No need to set up any routing. In a unit test, if you are using real routing, you're involving unnecessary side effects that could affect what you are really trying to test, which is just the behavior of the component. And the behavior of the component is to simply call the navigate
method. It doesn't need to test that the router works. Angular already guarantees that.
这篇关于Angular 2最终释放路由器单元测试的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!