如何测试Angular2的router.navigate?

时间:2016-10-28 07:41:48

标签: unit-testing angular angular2-testing

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

这是代码:

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

现在我想为此编写单元测试。

这是我开始考试的方式:

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

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

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

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

4 个答案:

答案 0 :(得分:43)

  

我可以模拟路由器并创建自己的导航功能,但那么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']);

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

答案 1 :(得分:2)

     it(`editTemplate() should navigate to template build module with query params`, inject(
        [Router],
        (router: Router) => {
          let id = 25;
          spyOn(router, "navigate").and.stub();
          router.navigate(["/template-builder"], {
            queryParams: { templateId: id }
          });
          expect(router.navigate).toHaveBeenCalledWith(["/template-builder"], {
            queryParams: { templateId: id }
          });
        }
      ));

答案 2 :(得分:0)

如果您想在不模拟路由器的情况下测试路由器,则可以将其注入测试中,然后直接在此处进行导航方法的监视。 .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']);
    }));
  });

答案 3 :(得分:0)

这对我有用

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