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