咱們知道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);
這時咱們就達到了咱們測試的目的。
咱們啓動測試,發現咱們原本的選擇下拉框變成了文字,這就是咱們假的子組件的效果。
咱們進行單元測試,就須要除被測組件外,其餘引用組件儘可能爲假,才能達到咱們的目的。