看這樣一段代碼:
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方法,得到其在單元測試過程中實際調用的次數。

expect方法:基于傳入的spec建立一個expectation. 在我們的例子裡,傳入的spec就是keyboardFocusService.findFirstFocusable被spy之後的版本:
Expectation通過工廠方法建立,該工廠方法接受兩個參數,第一個參數為spied method handle:
第二個參數為單元測試代碼運作的spec資訊,即下圖高亮代碼:
Expectation工廠方法的實作細節,我們可以略過:
toHaveBeenCalledTimes的函數體是之前wrapSyncCompare包裹函數傳回的一個閉包:
待compare的業務邏輯寫在函數matcherFactory裡:
以後我們可以直接在函數toHaveBeenCalledTimes裡設定斷點調試。
檢查傳入的actual是否是一個spied後的函數。
将檢查結果設定成預設值false.
檢查傳入的期望調用次數的值的資料類型是否是Number
Spied版本的函數調用明細,存儲在CallTracker的calls屬性裡:
這個數組裡包含的監控到的方法調用資訊有:
方法調用的輸入參數
調用方法的執行個體對象
調用方法的傳回參數
"get the number of invocations of this spy"的實作方法:calls.length
如果calls.length和傳入的期望值expected相等,說明比對成功,傳回success結果: