How to test Angular2 router.navigate?

I missed the <router-outlet> messages in other unit tests, but to have a good isolated example, I created AuthGuard that checks if a user is logged in for specific actions.

This is the code:

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

Now I want to write unit test for this.

This is how I start the test:

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

I created a DummyComponent that does nothing. Now my test. Imagine that the service returns false and runs this.router.navigate(['/login']) :

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

This will result in exclusion from the section β€œUnable to find bootable first outlet”. Obviously, I can use toThrow() instead of toBe(false) , but this does not seem like a very reasonable solution. Since I'm testing the service here, there is no template where I can put the <router-outlet> . I could mock the router and make my own navigation function, but then what is the point of the RouterTestingModule? You might even want to check how the navigation works.

+21
source share
2 answers

I could mock the router and make my own navigation function, but then what is the point of the RouterTestingModule? You might even want to check how the navigation works.

There is no real point. If it’s just a unit test for an auth protector, then just mock and mock spy to verify that the navigate method was called with the login argument

 let router = { navigate: jasmine.createSpy('navigate') } { provide: Router, useValue: router } expect(authGuardService.canActivate(<any>{}, <any>{})).toBe(false); expect(router.navigate).toHaveBeenCalledWith(['/login']); 

This is how unit tests should usually be written. To try to test any real real navigation, it probably falls under general testing.

+41
source

If you want to test the router without mocking it, you can simply insert it into your test and then spy directly on the navigation method. .and.stub() will make the call do nothing.

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

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


All Articles