web-dev-qa-db-fra.com

Comment tester le routeur.navigate de Angular2?

J'ai rencontré des messages manquants <router-outlet> Dans d'autres tests unitaires, mais juste pour avoir un exemple isolé de Nice, j'ai créé un AuthGuard qui vérifie si un utilisateur est connecté pour certaines actions.

C'est le code:

canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
    if (!this.authService.isLoggedIn()) {
        this.router.navigate(['/login']);
        return false;
    }
    return true;
}

Maintenant, je veux écrire un test unitaire pour cela.

Voici comment je commence mon test:

beforeEach(() => {
    TestBed.configureTestingModule({
        imports: [
            RouterTestingModule.withRoutes([
                {
                    path: 'login',
                    component: DummyComponent
                }
            ])
        ],
        declarations: [
            DummyComponent
        ],
        providers: [
            AuthGuardService,
            {
                provide: AuthService,
                useClass: MockAuthService
            }
        ]
    });
});

J'ai créé un DummyComponent qui ne fait rien. Maintenant mon test. Supposons que le service retourne false et qu'il déclenche this.router.navigate(['/login']):

it('should not let users pass when not logged in', (): void => {
    expect(authGuardService.canActivate(<any>{}, <any>{})).toBe(false);
});

Cela lève une exception avec "Impossible de trouver la sortie principale à charger". Évidemment, je peux utiliser toThrow() au lieu de toBe(false), mais cela ne semble pas être une solution très judicieuse. Puisque je teste un service ici, il n’existe aucun modèle dans lequel je puisse placer la balise <router-outlet>. Je pourrais me moquer du routeur et créer ma propre fonction de navigation, mais quel est l'intérêt de RouterTestingModule? Vous voulez peut-être même vérifier que la navigation a bien fonctionné.

27
Bart

Je pourrais me moquer du routeur et créer ma propre fonction de navigation, mais quel est l'intérêt de RouterTestingModule? Vous voulez peut-être même vérifier que la navigation a bien fonctionné.

Il n'y a pas de vrai point. S'il ne s'agit que d'un test unitaire pour le gardien d'authentification, il suffit alors de simuler et d'espionner le simulateur pour vérifier que sa méthode navigate a été appelée avec l'argument login.

let router = {
  navigate: jasmine.createSpy('navigate')
}

{ provide: Router, useValue: router }

expect(authGuardService.canActivate(<any>{}, <any>{})).toBe(false);
expect(router.navigate).toHaveBeenCalledWith(['/login']);

C’est ainsi que les tests nit devraient normalement être écrits. Essayer de tester toute navigation réelle réelle, cela tomberait probablement dans le cadre de tests de bout en bout.

48
Paul Samsotha

cela a fonctionné pour moi

describe('navigateExample', () => {
    it('navigate Example', () => {
        const routerstub: Router = TestBed.get(Router);
        spyOn(routerstub, 'navigate');
        component.navigateExample();
    });
});
3
alapofa83

Si vous souhaitez tester le routeur sans vous moquer de lui, vous pouvez simplement l'injecter dans votre test, puis espionner directement la méthode de navigation correspondante. La .and.stub() fera en sorte que l'appel ne fasse rien.

describe('something that navigates', () => {
    it('should navigate', inject([Router], (router: Router) => {
      spyOn(router, 'navigate').and.stub();
      expect(authGuardService.canActivate(<any>{}, <any>{})).toBe(false);
      expect(router.navigate).toHaveBeenCalledWith(['/login']);
    }));
  });
2
Chris Putnam