web-dev-qa-db-fra.com

Test unitaire du routeur de libération finale angulaire 2

Comment puis-je tester les routeurs dans la version angulaire 2.0.0 avec le karma et le jasmin?

Voici à quoi ressemble mon ancien test unitaire dans la 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));
  });

});

27
xphong

Pour tester, nous créons maintenant un module de test utilisant TestBed . Nous pouvons utiliser le TestBed#configureTestingModule et lui transmettre un objet de métadonnées de la même manière que nous le transmettrions à @NgModule

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

Pour le routage, au lieu d'utiliser la variable normale RouterModule, nous utiliserions plutôt RouterTestingModule . Ceci configure les Router et Location, de sorte que vous n'avez pas besoin de vous-même. Vous pouvez également y emprunter des routes en appelant RouterTestingModule.withRoutes(Routes)

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

Pour obtenir Location et Router dans le test, la même chose fonctionne, comme dans votre exemple. 

let router, location;

beforeEach(() => {
  TestBed...
});

beforeEach(inject([Router, Location], (_router: Router, _location: Location) => {
  router = _router;
  location = _location;
}));

Vous pouvez également injecter dans chaque test si nécessaire

it('should go home',
    async(inject([Router, Location], (router: Router, location: Location) => {
})));

La async ci-dessus est utilisée comme done sauf que nous n'avons pas besoin d'appeler explicitement done. Angular le fera pour nous une fois toutes les tâches asynchrones terminées.

Une autre façon d’obtenir les fournisseurs est de passer au banc d’essai.

let location, router;

beforeEach(() => {
  TestBed.configureTestingModule({
    imports: [RouterTestingModule.withRoutes([
      { path: 'home', component: DummyComponent }
    ])],
  });
  let injector = getTestBed();
  location = injector.get(Location);
  router = injector.get(Router);
});

Voici un test complet, refactoring votre exemple

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

METTRE À JOUR

De plus, si vous voulez simplement simuler le routeur, ce qui pourrait être le meilleur moyen de procéder à un test unitaire, vous pouvez simplement le faire.

let routerStub;

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

Et dans vos tests, tout ce que vous voulez faire est de vérifier que le stub est appelé avec le bon argument, lorsque le composant interagit avec celui-ci.

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

À moins que vous ne souhaitiez réellement tester un routage, c'est probablement la voie à suivre. Pas besoin de configurer un routage. Dans un test unitaire, si vous utilisez un routage réel, vous induisez des effets secondaires inutiles qui pourraient affecter ce que vous essayez réellement de tester, à savoir le comportement du composant. Et le comportement du composant est simplement d'appeler la méthode navigate. Il n'est pas nécessaire de vérifier que le routeur fonctionne. Angular garantit déjà cela.

80
Paul Samsotha

Au lieu d'utiliser useValue pour routerStub, vous pouvez utiliser useClass dans providers et cela a vraiment fonctionné pour moi.

export class RouterStub {
  public url: string = '/';
  constructor() { }
    enter code here
  navigateByUrl(url: any) {
    this.url = url;
  }
}

Et dans la beforeEach, il suffit d'instancier l'objet routerStub comme

routerStub = new RouterStub()    

Et dans les cas de test

component.router.navigateByUrl('/test');
fixture.detectChanges();
0
karthik kannan B

Bonne approche suggérée par Paul J'ai également configuré mon routage de la même manière mais en plus, j'ai ajouté un service permettant de mettre à jour certaines données pour le routage, puis de vérifier l'emplacement actuel.

afin que vous puissiez ajouter un service pour mettre à jour les données sur les composants qui rendent certaines données et ensuite vérifier la navigation.

configurer ci-dessous dans TestBed.configureTestingModule

providers : [MyService]

puis créer obtenir un service dans foreach

myService= TestBed.get(MyService);

mettre à jour des données de service comme 

myService.someMethodCall();

De cette façon, vous pouvez jouer après un rendu de données.

0
Vijay Barot