web-dev-qa-db-fra.com

Angular 2/4/6/7 - Test unitaire avec routeur

Dans Angular 2.0.0, je suis en train de tester un composant qui utilise un routeur. Cependant, je reçois le message d'erreur "Les paramètres fournis ne correspondent à aucune signature de la cible de l'appel.". Dans le code Visual Studio dans spec .ts c'est le nouveau Router () qui est surligné en rouge

J'apprécie vraiment si quelqu'un pouvait me faire savoir quelle serait la syntaxe correcte? Merci d'avance. Mon code comme suit:

spec.ts

import { TestBed, async } from '@angular/core/testing';
import { NavToolComponent } from './nav-tool.component';
import { ComponentComm } from '../../shared/component-comm.service';
import { Router } from '@angular/router';

describe('Component: NavTool', () => {
  it('should create an instance', () => {
    let component = new NavToolComponent( new ComponentComm(), new Router());
    expect(component).toBeTruthy();
  });
});

Constructeur de composants

constructor(private componentComm: ComponentComm, private router: Router) {}
47
Ka Tech

Vous pouvez aussi simplement utiliser le RouterTestingModule et juste spyOn la fonction de navigation comme ceci ...

import { TestBed } from '@angular/core/testing';
import { RouterTestingModule } from '@angular/router/testing';
import { Router } from '@angular/router';

import { MyModule } from './my-module';
import { MyComponent } from './my-component';

describe('something', () => {

    let fixture: ComponentFixture<LandingComponent>;
    let router: Router;

    beforeEach(() => {

        TestBed.configureTestingModule({
            imports: [
                MyModule,
                RouterTestingModule.withRoutes([]),
            ],
        }).compileComponents();

        fixture = TestBed.createComponent(MyComponent);
        router = TestBed.get(Router)

    });

    it('should navigate', () => {
        let component = fixture.componentInstance;
        let navigateSpy = spyOn(router, 'navigate');

        component.goSomewhere();
        expect(navigateSpy).toHaveBeenCalledWith(['/expectedUrl']);
    });
});
90
Lenny

C'est parce que le Route a certaines dépendances qu'il s'attend à transmettre à son constructeur.

Si vous utilisez des composants Angular, vous ne devriez pas essayer de faire des tests isolés. Vous devez utiliser l'infrastructure de test Angular pour préparer l'environnement de test. Cela signifie laisser Angular créer le composant, le laisser inject toutes les dépendances requises, au lieu d'essayer de tout créer.

Pour commencer, vous devriez avoir quelque chose comme

import { TestBed } from '@angular/core/testing';

describe('Component: NavTool', () => {
  let mockRouter = {
    navigate: jasmine.createSpy('navigate')
  };
  beforeEach(() => {
    TestBed.configureTestingModule({
      declarations: [ NavToolComponent ],
      providers: [
        { provide: Router, useValue: mockRouter },
        ComponentComm
      ]
    });
  });
  it('should click link', () => {
    let fixture = TestBed.createComponent(NavToolComponent);
    fixture.detectChanges();
    let component: NavToolComponent = fixture.componentInstance;
    component.clickLink('home');
    expect(mockRouter.navigate).toHaveBeenCalledWith(['/home']);
  });
});

Ou quelque chose comme ça. Vous utilisez le TestBed pour configurer un module à partir de rien pour le test. Vous le configurez à peu près de la même manière avec un @NgModule.

Ici, nous nous moquons du routeur. Dans la mesure où nous ne faisons que tester les unités, nous ne souhaitons peut-être pas utiliser le véritable service de routage. Nous voulons simplement nous assurer qu'il est appelé avec les bons arguments. Le simulacre et espion sera en mesure de capturer cet appel pour nous.

Si vous faites voulez utiliser le vrai routeur, vous devez utiliser le RouterTestingModule, où vous pouvez configurer des itinéraires. Voir un exemple ici et ici

Voir aussi:

20
Paul Samsotha

Jasmine va mieux avec des objets d'espionnage complets ...

describe(..., () => {
    const router = jasmine.createSpyObj('Router', ['navigate’]);
    ...
    beforeEach(async(() => {
        TestBed.configureTestingModule({
            providers: [  { provide: Router, useValue: router } ],
            ...
    });        
});
1
jkyoutsey

Voici un exemple si nous injectons le service Route dans notre contrôleur de composant:

import { TestBed, async } from '@angular/core/testing';
import { RouterTestingModule } from '@angular/router/testing'; // Because we inject service in our component
import { Router } from '@angular/router'; // Just if we need to test Route Service functionality

import { AppComponent } from './app.component';
import { DummyLoginLayoutComponent } from '../../../testing/mock.components.spec'; // Because we inject service in your component

describe('AppComponent', () => {
  let router: Router; // Just if we need to test Route Service functionality

  beforeEach(async(() => {
    TestBed.configureTestingModule({
      declarations: [
        AppComponent,
        DummyLoginLayoutComponent // Because we inject service in our component
      ],
      imports: [
        RouterTestingModule.withRoutes([
          { path: 'login', component: DummyLoginLayoutComponent },
        ]) // Because we inject service in our component
      ],
    }).compileComponents();

    router = TestBed.get(Router); // Just if we need to test Route Service functionality
    router.initialNavigation(); // Just if we need to test Route Service functionality
  }));

  it('should create the app', async(() => {
    const fixture = TestBed.createComponent(AppComponent);
    const app = fixture.debugElement.componentInstance;
    expect(app).toBeTruthy();
  }));
});

Nous pouvons également tester d'autres fonctionnalités telles que navigate(). Au cas où:

it('should call eventPage once with /register path if event is instanceof NavigationStart', fakeAsync(() => {
    spyOn(analyticService, 'eventPage');
    router.navigate(['register'])
      .then(() => {
        const baseUrl = window.location.Origin;
        const url = `${baseUrl}/register`;
        expect(analyticService.eventPage).toHaveBeenCalledTimes(1);
        expect(analyticService.eventPage).toHaveBeenCalledWith(url);
      });
}));

Mon fichier avec tous les composants fictifs (mock.components.specs.ts)

import { Component } from '@angular/core';

@Component({
    selector: 'home',
    template: '<div>Dummy home component</div>',
    styleUrls: []
})

export class DummyHomeComponent { }