Angular 5和Jasmine-如何模拟activeRoute.firstChild以测试ngOnDestroy上的退订

时间:2018-10-01 12:44:09

标签: angular unit-testing

在我的Angular组件中,使用以下代码创建两个可观察对象

this.navigationEnd = this.router.events.subscribe((event: any) => {
  // do some stuff
});

if (this.activeRoute.firstChild) {
  this.activeRouteChild = this.activeRoute.firstChild.params.subscribe((routeParams) => {
    // do some stuff
  });
}

如您所见,我订阅了activeRoute和router.events。作为一名优秀的程序员,当使用ngOnDestroy

销毁组件时,请确保同时退订
public ngOnDestroy(): void {
  if (this.navigationEnd) {
    this.navigationEnd.unsubscribe();
  }
  if (this.activeRouteChild) {
    this.activeRouteChild.unsubscribe();
  }
}

现在这很棒,但是是时候测试销毁组件时两个项目都退订了,这是我的测试

describe('ngOnDestroy', () => {
  it('should unsubscribe from navigationEnd & activeRouteChild on ngOnDestroy', () => {
    // arrange

    fixture.detectChanges();

    // act
    instance.ngOnDestroy();

    // assert
    expect((instance as any).navigationEnd.closed).toBeTruthy();
    expect((instance as any).activeRouteChild.closed).toBeTruthy();
  });
});

我像这样模拟Router和ActivatedRoute:

class MockRouter {
  // Router
  public events = of(new NavigationEnd(1, 'url/1', 'url/1'));
  public navigate = () => true;
}

class MockActivatedRoute {
  public firstChild = {params: of({id: '1'})};
}

这就是我在providers数组中声明它们的方式:

{provide: Router, useClass: MockRouter },
{provide: ActivatedRoute, useValue: MockActivatedRoute}

模拟路由器运行良好,但是它们与MockActivatedRoute有关,因为我认为我错误地实现了firstChild属性。我收到错误消息“ TypeError:无法读取未定义的'closed'属性”-我的问题是如何正确模拟ActivatedRoute及其firstChild属性?

1 个答案:

答案 0 :(得分:-1)

您不需要类来模拟子路线,只需在测试中通过调用带有必要参数的Navigation导航到那里即可。您可以先测试您的应用程序是否未进行路由(检查您的路由路径是否为初始路由),然后通过检查导航后路由是否发生更改(检查您的路径是否为导航路径)来进行验证。然后,您可以检查此后是否取消订阅组件。

注释:就测试而言,我发现测试您未编写的API常常没有用,除非您为它们做贡献。 unsubscribe()可以正常工作,我们知道这是因为Angular的贡献者已经为此编写了测试。自己进行测试虽然不错,但通常已经浪费了时间,因为它已经在Angular源代码中进行了测试。