乐趣区

angular中delaydebounceTime等时间相关操作符单元测试的一种方法

在上篇文章中咱们讲述了如何在 angular 中的应用弹珠测试来模仿 http 异步申请。

应用弹珠测试的办法尽管很官网很正统,但因为其调度器的失效周期的设置起因,若要在单元测试中联合 fixture.detectChanges(); 在某个测试用例结束后持续与组件进行交互,则会产生 No test scheduler initialized! 错语。

在单元测试中手动的与组件进行交互虽不正规,但该计划无疑会让新成员感触到单元测试敌对性的一面,升高对其的排挤水平。

sample

比方以后有一组件的性能是当用户在 input 中输出相应的内容时,先应用 500ms 防抖阻止冗余的申请,在进行后盾的模仿异步申请:

组件相干代码:

    // 当输出发生变化时,500ms 稳固后从新由后盾拉取数据
    this.input.valueChanges.pipe(debounceTime(500),
      distinctUntilChanged(),
      switchMap(value => {
        this.tagName = value;
        
        // 申请后盾
        return this.tagService.findTop20ByCourseAndNameLike(this.state.courseId, value);
      })
    ).subscribe((tags: Array<Tag>) => {this.tags = tags;});

应用弹珠测试的服务层 tagService 相干代码:

  /**
   * 模仿实在后盾,异步返回数据
   */
  public findTop20ByCourseAndNameLike(courseId: number, name: string): Observable<Array<Tag>> {Assert.notNull(courseId, '课程 ID 未定义');

    const tags = new Array<Tag>();
    for (let i = 0; i < 20; i++) {
      tags.push(new Tag({id: randomNumber(),
        name: randomString('name'),
        course: new Course({id: randomNumber()})
      }));
    }
    
    // 应用弹珠测试返回 tags
    return cold('---(x|)', {x: tags});
  }

基于上述代码,在单元测试中若仅把单元测试的指标定格为单元测试,则不会有任何问题。

但如果咱们将单元测试的指标扩大为:不启动后盾的前提下,独自疾速开发前台相干组件。那么弹珠测试将无奈满足该需要:

当咱们看到单元测试生成的被测试组件时,总想点击一些功能性的按钮,用“眼睛”来确认本人的程序是正确的 —- 只管咱们晓得这并不是单元测试的正确用法,但却无法控制住本人的好奇心。

  fit('should create', fakeAsync(() => {expect(component).toBeTruthy();
    
    // 自动检测组件变动并从新组件渲染
    fixture.autoDetectChanges();}));

如上所示,咱们本期待输出某些字符后,cold()办法可能在肯定工夫后返回模仿后盾返回的数据,但却失去了 No test scheduler initialized! 的谬误。

集体猜测这可能是因为 jasmine-marbles 设置了无效上下文作用域造成的。

rxjs-marbles

rxjs-marbles提供了一种解决办法:让咱们能够在不应用补丁的状况下,应用 tick() 办法来模仿一般时钟以及 RxJS 调度器的工夫推动。

这使得咱们能够摈弃弹珠测试而改用 delay 的办法来实现异步模仿申请,更重要的:像 debounceTime 等一些工夫相干的操作符也可能被轻松的模仿。

装置

npm i rxjs-marbles --save-dev

应用

tagService

// 删除原弹珠测试
- return cold('---(x|)', {x: tags});

// 应用 of + delay 的办法来模仿异步提早申请
+ return of(tags).pipe(delay(500));

单元测试验证

应用 tick 进行模仿时钟推动:

import {fakeSchedulers} from 'rxjs-marbles/jasmine/angular';

  // fakeSchedulers 使咱们能够应用 tick()来模仿 rxjs 中的时钟推动
  it('input change', fakeSchedulers(() => {component.tags = [];
    component.input.setValue('hello');

    // 模仿推动第一个防抖
    tick(500);

    // 断言正确的推动了防抖操作符
    expect(component.tagName).toEqual('hello');

    // 断言因为异步 delay 的作用,组件中的 tags 未发生变化
    expect(component.tags.length).toEqual(0);

    // 模仿推动 tagService 中的 delay
    tick(500);

    // 断言胜利推动了 delay 操作符
    expect(component.tags.length).toBeGreaterThan(1);
  }));

组件交互成果

此时,咱们借助此单元测试生成的组件进行一些交互性的 测试

本文作者:河北工业大业梦云智开发团队 潘杰

退出移动版