Angular 2 最终发布路由器单元测试

新手上路,请多包涵

我如何使用 karma 和 jasmine 在 Angular 版本 2.0.0 中对路由器进行单元测试?

这是我的旧单元测试在版本 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));
  });

});

原文由 xphong 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 290
2 个回答

为了进行测试,我们现在使用 TestBed 创建一个测试模块。我们可以使用 TestBed#configureTestingModule 并将元数据对象传递给它,就像我们传递给 @NgModule 一样

beforeEach(() => {
  TestBed.configureTestingModule({
    imports: [ /* modules to import */ ],
    providers: [ /* add providers */ ],
    declarations: [ /* components, directives, and pipes */ ]
  });
});

对于路由,我们不使用普通的 RouterModule ,而是使用 RouterTestingModule 。这设置了 RouterLocation ,所以你不需要自己。您还可以通过调用 RouterTestingModule.withRoutes(Routes)

 TestBed.configureTestingModule({
  imports: [
    RouterTestingModule.withRoutes([
      { path: 'home', component: DummyComponent }
    ])
  ]
})

要在测试中获得 LocationRouter ,与您的示例相同。

 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) => {
})));

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');
    });
  }));
});

更新

另外,如果你想简单地模拟路由器,这实际上可能是进行单元测试的更好方法,你可以简单地做

let routerStub;

beforeEach(() => {
  routerStub = {
    navigate: jasmine.createSpy('navigate'),
  };
  TestBed.configureTestingModule({
    providers: [ { provide: Router, useValue: routerStub } ],
  });
});

在您的测试中,您要做的就是测试当组件与存根交互时是否使用正确的参数调用存根

expect(routerStub.navigate).toHaveBeenCalledWith(['/route']);

除非您真的想测试一些路由,否则这可能是首选方法。无需设置任何路由。在单元测试中,如果您使用的是真实路由,则会涉及不必要的副作用,这些副作用可能会影响您真正尝试测试的内容,这只是组件的行为。而组件的行为就是简单地调用 navigate 方法。它不需要测试路由器是否工作。 Angular 已经保证了这一点。

原文由 Paul Samsotha 发布,翻译遵循 CC BY-SA 4.0 许可协议

保罗 建议的好方法我也以相同的方式配置了我的路由,但另外我还添加了服务来更新一些路由数据,然后检查当前位置。

因此您可以添加服务以更新组件上的数据,该组件呈现一些数据然后将检查导航。

在 TestBed.configureTestingModule 下面配置

providers : [MyService]

然后在 foreach 中创建获取服务

myService= TestBed.get(MyService);

从服务中更新一些数据,例如

myService.someMethodCall();

这样你就可以在一些数据渲染发生后播放。

原文由 Vijay Barot 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题