首页 > 解决方案 > 等待 Jasmine 中的 Angular 路由器导航

问题描述

假设我有一个代码片段来测试:

我想使用 HTTP 测试控制器来匹配相应的请求。

以下代码显然不起作用

service.doStuff();
httpController.expectOne(...);

我尝试订阅 Angular 路由器的事件,但没有运气

router.events.subscribe(event => {
    if (event instanceof NavigationEnd) { // last event emitted
        httpController.expectOne(...); // still too early
    }
});

基本上我的测试失败了,因为我比真正的 http 调用(我可以调试,这在返回承诺后完成)过早地完成我的期望。router.navigate

代码来自doStuff

  from(this.router.navigate([], {
    relativeTo: this.activatedRoute,
    queryParams: {
      token: null
    },
    queryParamsHandling: 'merge'
  }))
    .pipe(switchMap(() => this.doRemotely()))
    .subscribe(result => {
      .....
    });
}

导航承诺返回后正确激活,doRemotely但我无法拦截它。

我正在考虑嘲笑路由器......关于在发出 HTTP 调用运行期望的正确方法有什么想法吗?

[编辑]callFake在 Jasmine 间谍上使用不太可能解决我的问题,因为在虚假承诺返回后我无法做出预期。然而,模拟路由器有助于隔离测试。

标签: angularunit-testingjasmine

解决方案


在测试中使用真实路由是一件棘手的事情。但是,您可以尝试执行类似于https://ng-mocks.sudo.eu/guides/route的操作,以便在测试中正确初始化路由:

describe('TestRoute:Route', () => {
  beforeEach(() => TestBed.configureTestingModule({
    // Providing a route testing module is important
    imports: [RouterTestingModule.withRoutes([
      // routes
    ])],
  }).compileComponents());

  // fakeAsync is important
  it('renders', fakeAsync(() => {
    const fixture = TestBed.createComponent(RouterOutlet);
    const router: Router = TestBed.inject(Router);
    const location: Location = TestBed.inject(Location);

    // First we need to initialize navigation.
    location.go('/1');
    if (fixture.ngZone) {
      fixture.ngZone.run(() => router.initialNavigation());
      tick(); // is needed for rendering of the current route.
    }

    // We should land to the desired route.
    expect(location.path()).toEqual('/1');
  }));
});

推荐阅读