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

i042416發表於2021-02-21

看這樣一段程式碼:

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裡設定斷點除錯。

  1. 檢查傳入的actual是否是一個spied後的函式。
  2. 將檢查結果設定成預設值false.
  3. 檢查傳入的期望呼叫次數的值的資料型別是否是Number


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


Spied版本的函式呼叫明細,儲存在CallTracker的calls屬性裡:


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


這個陣列裡包含的監控到的方法呼叫資訊有:

  1. 方法呼叫的輸入引數
  2. 呼叫方法的例項物件
  3. 呼叫方法的返回引數 "get the number of invocations of this spy"的實現方法:calls.length


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


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


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


更多Jerry的原創文章,盡在:"汪子熙":

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


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/24475491/viewspace-2758154/,如需轉載,請註明出處,否則將追究法律責任。

相關文章