在上篇文章中咱们讲述了如何在 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);
}));
组件交互成果
此时,咱们借助此单元测试生成的组件进行一些交互性的 测试
本文作者:河北工业大业梦云智开发团队 潘杰