125 votes

Comment tester un composant qui dépend des paramètres de ActivatedRoute ?

Je teste un composant qui est utilisé pour modifier un objet. L'objet a un nom unique id qui est utilisé afin de saisir l'objet spécifique à partir d'un tableau d'objets qui sont hébergés dans un service. L'objet spécifique id est obtenu par le biais d'un paramètre qui est transmis via le routage, plus précisément par le biais de la fonction ActivatedRoute classe.

Le constructeur est le suivant :

 constructor(private _router:Router, private _curRoute:ActivatedRoute, private _session:Session) {
}

ngOnInit() {
    this._curRoute.params.subscribe(params => {
        this.userId = params['id'];
        this.userObj = this._session.allUsers.filter(user => user.id.toString() === this.userId.toString())[0];

Je veux exécuter des tests unitaires de base sur ce composant. Cependant, je ne suis pas sûr de la manière dont je peux injecter le composant id et le composant besoins ce paramètre.

Au fait : J'ai déjà une maquette pour le Session service, donc pas d'inquiétude à ce sujet.

165voto

zmanc Points 2545

La façon la plus simple de procéder est d'utiliser la fonction useValue et fournir un Observable de la valeur que vous voulez simuler.

RxJS < 6

import { Observable } from 'rxjs/Observable';
import 'rxjs/add/observable/of';
...
{
  provide: ActivatedRoute,
  useValue: {
    params: Observable.of({id: 123})
  }
}

RxJS >= 6

import { of } from 'rxjs';
...
{
  provide: ActivatedRoute,
  useValue: {
    params: of({id: 123})
  }
}

12 votes

Observable.of n'existe pas pour moi ! :S

4 votes

Importez Observable de rxjs/Observable

6 votes

Ce code provoque cette erreur dans mon projet : Uncaught NetworkError: Failed to execute 'send' on 'XMLHttpRequest': Failed to load 'ng:///DynamicTestModule/HomeContentComponent.ngfactory.js'. at http://localhost:9876/_karma_webpack_/polyfills.bundle.js:26‌​05

44voto

dimitris maf Points 113

En angulaire 8+, il y a le RouterTestingModule que vous pouvez utiliser pour avoir accès à la base de données de l'UE. ActivatedRoute o Router du composant. Vous pouvez également passer des routes à l'élément RouterTestingModule et créer des espions pour les méthodes d'acheminement demandées.

Par exemple, dans mon composant, j'ai :

ngOnInit() {
    if (this.route.snapshot.paramMap.get('id')) this.editMode()
    this.titleService.setTitle(`${this.pageTitle} | ${TAB_SUFFIX}`)
}

Et dans mon test, c'est le cas :

  beforeEach(async(() => {
    TestBed.configureTestingModule({
      declarations: [ ProductLinePageComponent ],
      schemas: [NO_ERRORS_SCHEMA],
      imports: [
        RouterTestingModule.withRoutes([])
      ],
    })
    .compileComponents()
  }))

  beforeEach(() => {
    router = TestBed.get(Router)
    route = TestBed.get(ActivatedRoute)
  })

et plus tard dans la section "ça" :

  it('should update', () => {
    const spyRoute = spyOn(route.snapshot.paramMap, 'get')
    spyRoute.and.returnValue('21')
    fixture = TestBed.createComponent(ProductLinePageComponent)
    component = fixture.componentInstance
    fixture.detectChanges()
    expect(component).toBeTruthy()
    expect(component.pageTitle).toBe('Edit Product Line')
    expect(component.formTitle).toBe('Edit Product Line')
    // here you can test the functionality which is triggered by the snapshot
  })

De la même manière, je pense que vous pouvez tester directement l'option paramMap via le spyOnProperty de jasmine, en retournant un observable ou en utilisant des billes rxjs. Cela pourrait faire gagner du temps et ne nécessite pas de maintenir une classe fantaisie supplémentaire. J'espère que c'est utile et que cela a du sens.

20voto

Colby Cox Points 492

J'ai trouvé comment faire !

Desde ActivatedRoute est un service, un service fictif peut être établi pour celui-ci. Appelons ce service fictif MockActivatedRoute . Nous allons étendre ActivatedRoute en MockActivatedRoute comme suit :

class MockActivatedRoute extends ActivatedRoute {
    constructor() {
        super(null, null, null, null, null);
        this.params = Observable.of({id: "5"});
    }

La ligne super(null, ....) initialise la super classe, qui a quatre paramètres obligatoires. Cependant, dans ce cas, nous n'avons besoin d'aucun de ces paramètres, donc nous les initialisons à null valeurs. Tout ce dont nous avons besoin est la valeur de params qui est un Observable<> . Par conséquent, avec this.params nous remplaçons la valeur de params et l'initialiser pour qu'il soit le Observable<> du paramètre sur lequel s'appuie le sujet du test.

Ensuite, comme tout autre service fictif, il suffit de l'initialiser et de remplacer le fournisseur du composant.

Bonne chance !

1 votes

C'est ce que je fais en ce moment même ! Cependant, j'obtiens des erreurs lorsque j'essaie d'utiliser la fonction super o Observable . D'où viennent-ils ?

0 votes

super() est intégré. Observable vient de rxjs/Observable ou simplement rxjs en fonction de votre version. Vous l'obtiendrez en utilisant import {Observable} from 'rxjs' .

0 votes

Vous avez accepté une réponse et posté une autre... si c'était Highlander (et il ne pouvait y en avoir qu'un), lequel avez-vous "vraiment" choisi et pourquoi ? C'est-à-dire que je pense que cela revient essentiellement à la même chose que la réponse de zmanc, que vous avez acceptée. Avez-vous trouvé une valeur ajoutée à la mise en place de ce simulacre [légèrement] plus compliqué ?

11voto

abdelrady Points 33

Voici comment je l'ai testé dans la dernière version d'angular 2.0...

import { ActivatedRoute, Data } from '@angular/router';

et dans la section Prestataires

{
  provide: ActivatedRoute,
  useValue: {
    data: {
      subscribe: (fn: (value: Data) => void) => fn({
        yourData: 'yolo'
      })
    }
  }
}

0 votes

Pouvez-vous fournir le code complet de la section des fournisseurs ?

0 votes

Il s'agit d'une classe de test unitaire complète. plnkr.co/edit/UeCKnJ2sCCpLLQcWqEGX?p=catalogue

0 votes

Comment tester le désabonnement dans ngOnDestroy ?

8voto

Shin Points 10934

Il suffit d'ajouter une copie de l'ActivatedRoute :

providers: [
  { provide: ActivatedRoute, useClass: MockActivatedRoute }
]

...

class MockActivatedRoute {
  // here you can add your mock objects, like snapshot or parent or whatever
  // example:
  parent = {
    snapshot: {data: {title: 'myTitle ' } },
    routeConfig: { children: { filter: () => {} } }
  };
}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X