如何测试Angular2的router.navigate?

Bar*_*art 29 unit-testing angular2-testing angular

<router-outlet>在其他单元测试中遇到了丢失的消息,但是为了得到一个很好的隔离示例,我创建了一个AuthGuard,用于检查用户是否已登录以执行某些操作.

这是代码:

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

现在我想为此编写一个单元测试.

这就是我开始测试的方式:

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

我创建了一个什么都不做的DummyComponent.现在我的考试.假设服务返回false并触发this.router.navigate(['/login']):

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

这将引发"无法找到要加载的主要插座"的异常.显然我可以使用toThrow()而不是toBe(false),但这似乎不是一个非常明智的解决方案.由于我在这里测试服务,因此没有模板可以放置<router-outlet>标签.我可以模拟路由器并创建自己的导航功能,但那么RouterTestingModule有什么意义呢?也许你甚至想检查导航是否有效.

Pau*_*tha 51

我可以模拟路由器并创建自己的导航功能,但那么RouterTestingModule有什么意义呢?也许你甚至想检查导航是否有效.

没有真正的意义.如果他只是auth后卫的单元测试,那么只需模拟并监视模拟,检查它的navigate方法是否被login参数调用

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

{ provide: Router, useValue: router }

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

这就是通常应该编写单元测试的方法.为了尝试测试任何实际的真实导航,这可能属于端到端测试的范畴.

  • 您没有_have_配置任何路由.如果你只是想让它为routerLink这样的指令编译,你只需要导入_without_调用withRoutes.对于任何可以工作的链接,您需要配置一些路由.在你的情况下,我们缺少的是一个带有`<router-outlet>`的组件.如果没有至少一个带插座的组件,则路由无法正常工作 (4认同)
  • 我实际上尝试了8种其他方法来使`router.navigate`期望通过,这是它起作用的唯一方法!说实话,不知道为什么。也许这是我测试中的事件顺序,直到报废了我的答案并回答你的答案时我才意识到,但是无论如何,w00t! (2认同)

Chr*_*nam 15

如果你想在不模拟的情况下测试路由器,你可以将它注入你的测试中,然后直接监视导航方法。该.and.stub()将使因此呼叫没有做任何事情。

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']);
    }));
  });
Run Code Online (Sandbox Code Playgroud)