Jest 測試框架 beforeEach 的設計原理解析

注销發表於2021-10-02

副標題:SAP Spartacus SSR 最佳化的單元測試分析之一 : beforeEach

文件

SAP Spartacus 裡這段程式碼:

originalEngine = jasmine
        .createSpy('ngExpressEngine')
        .and.callFake(() => originalEngineInstance);

該方法接受一個字串作為建立的 Spy 的名稱,返回一個新的 Spy 物件。

這個新建立的 spy 物件,還是位於 jasmine namespace 之下。

spy.and: 返回 SpyStrategy 例項:

接下來,我們就可以透過這個 spy 物件的 strategy 方法,指派這個 spy 去做一些事情了。

callFake:callFake(fn)

Tell the spy to call a fake implementation when invoked.

單步除錯 createSpy 方法:

轉交給 env:

在 jasmine 內部,新建 strategy dispatcher 和 callTracker:

wrapper 的 and 屬性,來自 strategy dispatcher 的 and 屬性:

createSpy 最後返回的是 wrapper:

wrapper.and 指向 strategy:

呼叫 strategy 的 callFake 方法:

其實就是把透過 callFake 傳入的函式,賦給 Strategy 物件的 plan 欄位:

callFake 是一個鏈式呼叫,返回 wrapper 即 span 本身:

同理,建立另一個 id 為 ngExpressEngineInstance 的 wrapper spy,將一個空的函式賦給 strategy 物件的 plan 屬性:

進入 decorator 的 get 方法,也就是我們要測試的方法:

此處 45行傳入的 originalEngine 為 spy.

執行這個 mock 方法:

並且以下列這些輸入引數執行 spy:

當 spy 被執行時,其執行的上下文會自動被 jasmine 框架所記錄,這是透過 callTracker 完成的。

returnValue,則是透過 strategyDispatcher 所指定。

如果我們的單元測試程式碼裡,使用 and 指定了這個 spy 被呼叫之後,應該返回什麼樣的值,則這些指定值,在上圖第 7687 行程式碼被返回。

在我們待測試的 get 方法裡,最終會執行 originalEngine.

而這個 engine 已經被 spy 過了,所以執行 spy 後的版本。

mock 之後的 originalEngine,被呼叫時,會返回其 callFake 方法指定的函式的返回值,即 originalEngineInstance.

其原因如下,因為 spyStrategy 的 exec 方法,執行的函式就是之前用 callFake 呼叫,繫結到 plan 屬性指向的函式:originalEngine = strategy.callFake(() => originalEngineInstance);

這個 originalEngineInstance 也是一個 spy:

返回的 originalEngineInstance:

只要使用 spy 過的函式進行呼叫,則呼叫時傳入的引數和返回值必定會被 jasmine 記錄在案:

使用 mock 過的 spy 呼叫,記錄這三個輸入引數:

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

相關文章