天天看點

Angular單元測試架構裡API toHaveBeenCalledTimes的工作原理

看這樣一段代碼:

let spiedFirstFocusable = spyOn(
      keyboardFocusService,
      'findFirstFocusable'
    ).and.returnValue(el);
    fixture.detectChanges();

    expect(document.activeElement.id).toEqual('a');
    expect(spiedFirstFocusable).toHaveBeenCalledTimes(ELEMENT_FOCUSED_TIME);
      

spiedFirstFocusable是spyOn方法針對執行個體keyboardFocusService的findFirstFocusable方法進行監控後傳回的句柄。借助該句柄,我們可以使用toHaveBeenCalledTimes方法,得到其在單元測試過程中實際調用的次數。

Angular單元測試架構裡API toHaveBeenCalledTimes的工作原理

expect方法:基于傳入的spec建立一個expectation. 在我們的例子裡,傳入的spec就是keyboardFocusService.findFirstFocusable被spy之後的版本:

Angular單元測試架構裡API toHaveBeenCalledTimes的工作原理

Expectation通過工廠方法建立,該工廠方法接受兩個參數,第一個參數為spied method handle:

Angular單元測試架構裡API toHaveBeenCalledTimes的工作原理

第二個參數為單元測試代碼運作的spec資訊,即下圖高亮代碼:

Angular單元測試架構裡API toHaveBeenCalledTimes的工作原理

Expectation工廠方法的實作細節,我們可以略過:

Angular單元測試架構裡API toHaveBeenCalledTimes的工作原理

toHaveBeenCalledTimes的函數體是之前wrapSyncCompare包裹函數傳回的一個閉包:

Angular單元測試架構裡API toHaveBeenCalledTimes的工作原理

待compare的業務邏輯寫在函數matcherFactory裡:

Angular單元測試架構裡API toHaveBeenCalledTimes的工作原理
Angular單元測試架構裡API toHaveBeenCalledTimes的工作原理

以後我們可以直接在函數toHaveBeenCalledTimes裡設定斷點調試。

檢查傳入的actual是否是一個spied後的函數。

将檢查結果設定成預設值false.

檢查傳入的期望調用次數的值的資料類型是否是Number

Spied版本的函數調用明細,存儲在CallTracker的calls屬性裡:

Angular單元測試架構裡API toHaveBeenCalledTimes的工作原理

這個數組裡包含的監控到的方法調用資訊有:

方法調用的輸入參數

調用方法的執行個體對象

調用方法的傳回參數

"get the number of invocations of this spy"的實作方法:calls.length

如果calls.length和傳入的期望值expected相等,說明比對成功,傳回success結果: