Unit testing Angular 2 authGuard; spy method is not called

I am trying to run a unit test of my guard service. I managed to get this far from this answer , but now when I run the unit test for this, it says Expected spy navigate to have been called .

How to make my spy router used as this.router in a service?

Auth-guard.service.ts

 import { Injectable } from '@angular/core'; import { Router, CanActivate } from '@angular/router'; @Injectable() export class AuthGuardService { constructor(private router:Router) { } public canActivate() { const authToken = localStorage.getItem('auth-token'); const tokenExp = localStorage.getItem('auth-token-exp'); const hasAuth = (authToken && tokenExp); if(hasAuth && Date.now() < +tokenExp){ return true; } this.router.navigate(['/login']); return false; } } 

Auth-guard.service.spec.ts

 import { TestBed, async, inject } from '@angular/core/testing'; import { RouterTestingModule } from '@angular/router/testing'; import { AuthGuardService } from './auth-guard.service'; describe('AuthGuardService', () => { let service:AuthGuardService = null; let router = { navigate: jasmine.createSpy('navigate') }; beforeEach(() => { TestBed.configureTestingModule({ providers: [ AuthGuardService, {provide:RouterTestingModule, useValue:router} ], imports: [RouterTestingModule] }); }); beforeEach(inject([AuthGuardService], (agService:AuthGuardService) => { service = agService; })); it('checks if a user is valid', () => { expect(service.canActivate()).toBeFalsy(); expect(router.navigate).toHaveBeenCalled(); }); }); 

Replacing RouterTestingModule with a Router , as in the example answer throws Unexpected value 'undefined' imported by the module 'DynamicTestModule' .

+5
source share
2 answers

Instead of stubbing a router, use dependency injection and a spy using the router.navigate() method:

 import { TestBed, async, inject } from '@angular/core/testing'; import { RouterTestingModule } from '@angular/router/testing'; import { Router } from '@angular/router'; import { AuthGuardService } from './auth-guard.service'; describe('AuthGuardService', () => { beforeEach(() => { TestBed.configureTestingModule({ providers: [AuthGuardService], imports: [RouterTestingModule] }); }); it('checks if a user is valid', // inject your guard service AND Router async(inject([AuthGuardService, Router], (auth, router) => { // add a spy spyOn(router, 'navigate'); expect(auth.canActivate()).toBeFalsy(); expect(router.navigate).toHaveBeenCalled(); }) )); }); 

https://plnkr.co/edit/GNjeJSQJkoelIa9AqqPp?p=preview

+12
source

For this test, you can use ReflectiveInjector to resolve and create an auth-gaurd service object with dependencies.

But instead of conveying the actual dependency on the router, specify your own router class (RouterStub), which has a navigation function. Then spy on the nested Stub to check if the navigator is called.

 import {AuthGuardService} from './auth-guard.service'; import {ReflectiveInjector} from '@angular/core'; import {Router} from '@angular/router'; describe('AuthGuardService', () => { let service; let router; beforeEach(() => { let injector = ReflectiveInjector.resolveAndCreate([ AuthGuardService, {provide: Router, useClass: RouterStub} ]); service = injector.get(AuthGuardService); router = injector.get(Router); }); it('checks if a user is valid', () => { let spyNavigation = spyOn(router, 'navigate'); expect(service.canActivate()).toBeFalsy(); expect(spyNavigation).toHaveBeenCalled(); expect(spyNavigation).toHaveBeenCalledWith(['/login']); }); }); class RouterStub { navigate(routes: string[]) { //do nothing } } 
+1
source

Source: https://habr.com/ru/post/1262389/


All Articles