关于angular:Angular弹珠测试中由于未获取路由参数导致数据不返回的问题

115次阅读

共计 2153 个字符,预计需要花费 6 分钟才能阅读完成。

概述

最近在进行 angular 单元测试在组件初始化渲染方面的测试,应用的是 RxJS 提供的弹珠测试来模仿 http 申请提早。

然而在某些编辑组件中,ngOnInit 办法中应用了 router 来获取路由参数。在单元测试中,组件不会接管真的路由参数,因而并没有接管到测试数据,初始化时,渲染的组件是空数据。

本文的目标,是通过手动发送路由参数,来使组件胜利获取测试数据。

本文应用的技术基于:angularu 在单元测试中如何模仿 HTTP 申请提早

问题复现

在未呈现问题的状况下,当咱们为服务层设置好测试桩、在测试文件中模仿好返回值之后,启动测试之后,组件会失常渲染,并且会填入模仿返回的随机数据。
如果在断言非空的语句 Assert.isDefined 前面退出 console.log,控制台能够输入字符串。

如下:


然而,在起初测试的这几个组件中,依照示例代码写完、测试之后,渲染的组件并没有模仿数据,而是空组件。
尽管测试也能通过,但通过是因为断言的代码基本没有执行,代码中退出 console.log,控制台没有输入。如下:


只管在这种状况下,单元测试也能通过,但事实上,因为基本没有接管到返回值,咱们无奈验证服务层的返回值是否正确,这种做法对我的项目来说,是不负责任的,这增大了生产环境出错的危险。

问题剖析

先上组件的 ngOnInit 初始化代码:


  ngOnInit() {this.getEditCollege();
  }

  /**
   * 获取要编辑的学院
   */
  public getEditCollege() {
    // 发动订阅,获取路由参数,取得参数后执行回调
    this.route.params.subscribe((params: {id: number}) => {console.log("subscribe");
      this.collegeService.getCollegeById(params.id).subscribe((data) => {Assert.isDefined(data.id, 'id');
        Assert.isDefined(data.name, 'name');
        Assert.isDefined(data.code, 'code');
        Assert.isDefined(data.number, 'number');
        console.log("college->edit");
        this.initForm(data);
      });
    });
  }

通过演绎发现,所有出错的组件都有用 route 获取路由参数的过程:发动订阅,当后果返回时执行回调办法,向服务层获取对象。

用打断点的形式得出结论,route 发动的订阅基本没有返回,因而前面的回调办法也就没有执行。

因为 route 是通过路由的变动,来获取参数路由参数的,但在单元测试中,路由并不会发生变化。

所以须要用一个假的 ActiveRouteStub 来代替真的 ActiveRoute 实现单元测试。

ActiveRouteStub

/**
 * ActiveRouteStub
 * 路由性能服务桩
 */

import {Observable, Subject} from 'rxjs';

export class ActivatedRouteStub {paramsSubject = new Subject<any>();
  params: Observable<any>;
  parent: any;
  snapshot = {
    paramMap: {get: () => {return 0;}
    }
  };

  constructor() {this.params = this.paramsSubject.asObservable();
  }
}

而后从 Provider 引入(也能够引入到单元测试专用的辅助模块中,例如ServiceTestingModule):

  providers: [{provide: ActivatedRoute, useClass: ActivatedRouteStub}
  ]

在测试类中扭转路由参数

接下来通过代码,收到扭转路,传入和组件接管的类型绝对应的参数(示例组件中应用 ID):

  it('should create', fakeAsync(() => {
    // 字段断言,调用 getCollegeById
    expect(component).toBeTruthy();
    // 尝试获取真的,实际上获取的假的
    const route = TestBed.get(ActivatedRoute) as ActivatedRouteStub;
    // 发送路由参数,参数为要编辑的对象的 ID
    route.paramsSubject.next({id: randomNumber()});
  }));

成果

这样,因为 route 发动的订阅有了返回值,回调办法被执行,所以被测组件就能取得测试数据。

只有当测试数据真真切切的被填入组件中,咱们能力判定这个组件的初始化的确是失常的。

总结

单元测试中,咱们尝尝应用 RxJS 提供的弹珠测试来模仿 http 申请提早,因为 route 须要检测路由变动来获取参数,而单元测试中组件的路由不会发生变化,因而会造成订阅无奈返回的状况,进而导致测试时的组件渲染不失常。

解决办法就是应用 ActiveRouteStub 代替 ActiveRoute 实现测试,手动设置路由变动,以便前面的代码失常执行,使得被测组件能够获取到随机的测试数据,进而胜利渲染。

正文完
 0