咱们知道angular组件间通信有多种方法,其中最经常使用的一种方法就是借助于 @Input 和 @Output 进行通信。具体如何通信请参考angular组件间通信,本文再也不赘述,咱们来说讲关于此方法如何进行单元测试。git
咱们单元测试父组件与子组件的的交互是否符合咱们的要求,咱们在父组件进行测试,就须要模拟一个假的子组件出来,这样排除其余因素对测试的影响。
好比如今我在分页组件里写了一个每页大小选择组件,如今要测试一下组件间交互。如今分页组件就是咱们的父组件,每页大小组件就是咱们的子组件。咱们如今须要去模拟一个假的子组件出来。咱们先模拟一个假模块出来。
咱们的子组件在core模块里,咱们在core模块下创造一个core-testing模拟模块。再在core-testing模块下创造一个core组件,由于咱们是一个模拟模块,咱们只须要ts文件便可。segmentfault
@Component({ selector: 'app-size', template: ` <p> size-select works! </p> `, styles: [] }) export class SizeComponent implements OnInit { constructor() { } ngOnInit() { } }
为了咱们能够在父组件的测试文件中获得模拟的子组件,咱们还须要一个controller,在core-testing文件夹下建立一个core-testing-controller.ts文件。CoreTestingController类继承TestingController
。app
export class CoreTestingController extends TestingController { }
同时在咱们的core-testing.module里声明CoreTestingController为提供者async
providers: [ CoreTestingController ]
此时咱们的目录树ide
core-testing git:(134) ✗ tree . ├── core-testing-controller.ts ├── core-testing.module.ts ├── page │ └── page.component.ts └── size └── size.component.ts
由于咱们是模拟的子组件,因此咱们应该添加子组件的@Input 和 @Output,同时在构造函数里把这个模拟的子组件添加到CoreTestingController里。函数
export class SizeComponent implements OnInit { @Input() size: number; @Output() onChangeSize = new EventEmitter<number>(); constructor(private controller: CoreTestingController) { this.controller.addUnit(this); } }
此时咱们的准备工做就完成了。单元测试
首先咱们引入假组件并声明提供者测试
import {CoreTestingController} from '../core-testing/core-testing-controller'; import {SizeComponent} from '../core-testing/size/size.component'; beforeEach(async(() => { TestBed.configureTestingModule({ declarations: [ PageComponent, SizeComponent ], imports: [FormsModule], providers: [ CoreTestingController ] }) .compileComponents(); }));
我大家这里引入的是咱们创造的假的SizeComponent,由于咱们父组件与子组件在同一个模块里,因此咱们直接引入SizeComponent就能够。
此时咱们父组件想要子组件时就会使用假的子组件。
咱们先断言@Input,咱们断言父组件的值与咱们假的子组件值相等this
it('选择每页大小', () => { const controller = TestBed.get(CoreTestingController) as CoreTestingController; const sizeComponent = controller.get(SizeComponent) as SizeComponent; expect(sizeComponent.size).toBe(component.size); });
咱们这里的get方法就对应的咱们以前的构造函数的addUnit方法,具体参考TestingController类定义的方法。
而后咱们再断言子组件向父组件@Output也没有问题,咱们先spyon父组件接收子组件值的方法,而后定义一个变量并传给父组件,而后断言父组件接收到的值与子组件传的值相同。spa
spyOn(component, 'onSizeSelected'); const emitSize = 4; sizeComponent.onChangeSize.emit(emitSize); expect(component.onSizeSelected).toHaveBeenCalledWith(4);
这时咱们就达到了咱们测试的目的。
咱们启动测试,发现咱们原本的选择下拉框变成了文字,这就是咱们假的子组件的效果。
咱们进行单元测试,就须要除被测组件外,其余引用组件尽可能为假,才能达到咱们的目的。