Angular 单元测试实践 (5)

2022-06-05  本文已影响0人  品品下午茶

在 Angular 应用中,路由对整个应用的用户体验,起着非常重要的作用。因此,对路由进行单元测试,可以确保应用的正确和高效运行。

路由的单元测试工作,主要包括以下三个方面:

测试导航地址

在 Angular 应用中,通过在 a 元素上添加 routerLink 指令,实现路由功能。

在测试前,我们需要建立一个指令的 stub,避免做大量的工作去建立完整的 routerLink.

import { Directive, Input } from "@angular/core”;

@Directive({
  selector: '[routerLink]’
})
export class RouterLinkDirectiveStub {
  @Input('routerLink') linkParams: any;
}

在这里,selector 必须匹配 routerLink 指令,才能正常工作。我们会使用 routerLink 绑定,实现真实的 routerLink 指令的行为。这样,routerLink 指令的 linkParams 属性会把导航地址传递给 stub.

现在可以编写测试:

  it('should set up routerLink directives', () => {
    const linkDe = fixture.debugElement.queryAll(By.directive(RouterLinkDirectiveStub));
    const links = linkDe.map(de => de.injector.get(RouterLinkDirectiveStub));
    expect(links.length).toBe(2);
    expect(links[0].linkParams).toEqual('home’);
    expect(links[1].linkParams).toEqual(['heroes', 1]);
  });

  it('should get the id parameter', () => {
    expect(component.heroId).toBe(1);
  });

在测试用例中,我们使用 By 工具类的 directive 方法,指定查询元件的类型:组件或指令。 debugElement 属性的 queryAll 方法,返回了所有查询到的 routerLink 指令。然后,就可以对指令的数量,链接参数进行测试。

测试路由参数

  1. 调整提供导航的组件:
@Component({
  selector: 'app-menu’,
  templateUrl: './menu.component.html’,
  styleUrls: ['./menu.component.css’]
})
export class MenuComponent implements OnInit {

  bookId: number;

  constructor(private route: ActivatedRoute) { }

  ngOnInit(): void {
    this.route.paramMap.subscribe(params => this.bookId = + params.get('id’));
  }

}

在初始化函数中,对 paramMap 方法进行订阅,获得参数 id 对值。

  1. 创建一个 stub,模拟 paramMap 方法的行为:
export class ActivatedRouteStub {

  private subject = new ReplaySubject<ParamMap>();

  constructor(initialParams?: Params) {
    this.setParamMap(initialParams);
  }

  readonly paramMap = this.subject.asObservable();

  setParamMap(params?: Params) {
    this.subject.next(convertToParamMap(params));
  }
}

在这里,可以使用 constructor 构造函数或 setParamMap 设置路由参数。

  1. 编写单元测试:
…
  beforeEach(() => {
    const activatedRoute = new ActivatedRouteStub();
    activatedRoute.setParamMap({id: 1});

    TestBed.configureTestingModule({
      declarations: [
        MenuComponent,
        RouterLinkDirectiveStub,
        RouterOutletComponentStub
      ],
      providers: [
        { provide: ActivatedRoute, useValue: activatedRoute }
      ],
    })
    .compileComponents();
  });
...    
  it('should get the id parameter', () => {
    expect(component.bookId).toBe(1);
  });

首先,在测试初始化阶段,创建了 ActivatedRouteStub 类的一个实例,并设置参数 id 的值为 1. 然后,在配置测试模块时,把 activatedRoute 作为提供者进行添加。最后,我们验证组件的属性是否正确接收了来自路由参数的值。

测试加载组件

Angular 为我们提供了一个测试真实路由功能的类 RouterTestingModule,可以定义我们在测试时需要的路由:

TestBed.configureTestingModule({
  imports: [
    RouterTestingModule.withRoutes([{
      path: 'heroes/:id’,
      component: MenuComponent
    }])
  ],
  declarations: [MenuComponent]
});

通过使用这个方法,不仅可以测试路由的导航地址和路由参数,也可以测试是否正确加载组件。

为了测试加载组件,需要创建一个组件的 stub,提供 router-outlet,作为组件加载的占位符。

@Component({
  selector: 'router-outlet’,
  template: ‘'
})
export class RouterOutletComponentStub { }

最后,在配置测试模块的时候,可以为 schemas 属性添加 NO_ERRORS_SCHEMA。这样,就不必再去创建一个目标组件,Angular 会忽略任何在模板中不能识别的组件。

测试报表页面

路由测试报表页面
上一篇 下一篇

猜你喜欢

热点阅读