Angular 2最终释放路由器单元测试 [英] Angular 2 Final Release Router Unit Test

查看:131
本文介绍了Angular 2最终释放路由器单元测试的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如何使用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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆