紀念特洛伊英雄 Sinon - SAP UI5 Mock Server 使用步驟和工作原理介紹

這是 Jerry 2021 年的第 63 篇文章,也是汪子熙公衆號總共第 340 篇原創文章。

                                                 蜀相
                                                 杜甫

                                          丞相祠堂何處尋,
                                          錦官城外柏森森。

                                          映階碧草自春色,
                                          隔葉黃鸝空好音。

                                          三顧頻煩天下計,
                                          兩朝開濟老臣心。

                                          出師未捷身先死,
                                          長使英雄淚滿襟。

[圖片]1

[圖片]2

Jerry 前一篇文章 基於 OData 模型和 JSON 模型的 SAP UI5 表格控件行項目的添加和刪除實現,比較了 SAP UI5 表格控件使用 OData 模型和 JSON 模型的實現差異。

SAP UI5 初學者在學習 OData API 使用時,面臨的一個問題是:如何找到一些公網可以免費使用的 OData 服務。

Northwind 無疑是極佳的選擇之一,但是該服務不支持修改操作。

雖然從理論上講,我們可以使用按照 Jerry 的這篇文章,SAP Cloud Application Programming 介紹(2021 更新版),採用 SAP Cloud Application Programming 模型(CAP),自行在本地搭建一個支持增刪改查的 OData 服務,但是對於學習 SAP UI5 的初學者來說,未免有些大材小用。

其實 SAP UI5 自帶了一個很容易使用的 Mock Server,可以用來在本地模擬 OData 服務提供者,響應 SAP UI5 應用發起的 OData 請求,並使用預先配置好的測試數據進行回覆。

登錄 SAP UI5 官方網站,輸入關鍵字 Mock Server,即可找到其使用文檔:

https://sapui5.hana.ondemand.com/

[圖片]3

Mock Server 的運行對於 SAP UI5 應用來說是完全透明的,SAP UI5 應用根本不知道自己發出的請求,到底是被真實的遠端服務器響應,還是由 Mock Server 返回。

https://sapui5.hana.ondemand.com/

下面通過實際例子來介紹 Mock Server 的使用步驟。本例全部代碼,在我的 Github 可以獲得:

https://github.com/wangzixi-diablo/ui5-toolset/tree/main/tabledelete/webapp

(1) 在 Table 控制器裏,新建一個 OData 模型實例,傳入 OData 服務 url:

/here/goes/your/serviceUrl/

[圖片]4

該 url 就是我們需要在 Mock Server 裏模擬的 OData 服務地址。

(2) 本地工程文件裏新建一個 test 文件夾,其內包含下列三個文件:

metadata.xml: OData 服務的元數據文件,定義了名爲 Products 的 EntitySet,其類型爲 Product,後者包含三個字段:

ProductId
Name
Size

[圖片]5

Products.json

包含了上圖 metadata.xml 文件裏定義的名爲 Products 的 EntitySet 對應的數據。運行時,Mock Server 會自動到其工作目錄查找同名的 .json 文件,讀取其內容,返回給 OData 服務的消費者。

[圖片]6

server.js

從 sap/ui/core/util/MockServer 導入 Mock Server 的實現,將步驟一里 SAP UI5 需要消費的 OData 服務 url,傳入 Mock Server 的 rootUri 屬性即可。

下圖 autoRespondAfter 屬性,定義了使用 Mock Server 響應 OData 請求的延時,即 1 秒後返回響應。

[圖片]7

三個文件總共行數加起來不到60行,卻提供了一個功能完整的 Mock Server.

(3) 在該 SAP UI5 應用的 index.html 裏,使用 sap.ui.require 加載本地工程裏的 Mock Server 實例,調用其 init 方法,即可啓動該服務器。

[圖片]8

將 Jerry 的代碼克隆到本地,npm install 之後執行 node local.js:

https://github.com/wangzixi-diablo/ui5-toolset

即可在 Chrome 開發者工具裏觀察 Mock Server 的運行情況:

http://localhost:3002/tabledelete/?sap-ui-debug=true

(1) SAP UI5 表格控件請求 OData 服務的元數據。Mock Server 接收到該請求,將工作目錄下的 metadata.xml 的內容,返回給調用者。
[圖片]9

(2) Jerry 之前的文章 基於 OData 模型和 JSON 模型的 SAP UI5 表格控件行項目的添加和刪除實現 曾經提到,OData 模型是服務器端模型,這意味着表格控件根本不知道當前到底有多少條數據需要顯示。

因此 SAP UI5 表格控件會發送另一條包含 $count 操作的 OData 請求,去查詢 Products 總數。

最終在表格控件裏顯示的條目數,是 $count 操作的結果和 20 兩個數字的較小值。20 是 OData 分頁的默認尺寸,在 Jerry 的文章 SAP UI 搜索分頁技術 裏有詳細介紹。
[圖片]10

因爲我在 Mock Server 的 Products.json 裏只維護了兩條數據,故 $count 結果爲 2.

(3) 現在表格控件已經明確了自己需要顯示兩條數據,故發起第三個 OData 數據請求,skip=0&top=2, 向服務器請求第一頁的前兩條數據。

Mock Server 接收到該請求,將 Products.json 裏全部兩條數據返回給表格控件。

[圖片]11

(4) 當使用 Add Row 按鈕添加一條新的數據之後,SAP UI5 表格控件依次發送下列三條 OData 請求:

[圖片]12

刪除操作的執行邏輯類似,這裏不再贅述。

SAP UI5 Mock Server 的一些高級用法,可以通過查詢 Mock Server 的幫助文檔來獲取。

[圖片] 13

例如,假設我們期望針對 Mock Server 返回給調用者的數據,進行一些自定義處理。此時可以在 Mock Server 提供的 attachAfter 鉤子函數裏編寫自定義邏輯:

[圖片]14

如上圖所示,當 Products.json 文件的數據被 Mock Server 加載,準備返回給 OData 消費者之前,應用開發人員編寫的 attachAfter 回調函數觸發,將每個產品的 Name 字段值末尾,加上一個句號。

SAP UI5 Mock Server 實際上基於著名的開源 Mock 框架 Sinon.js:

https://github.com/sinonjs/sinon

[圖片]15

Sinon 框架的命名,是爲了向希臘聯軍與特洛伊人之間長達十年的戰爭期間湧現出的英雄戰士 Sinon(西農) 致敬,就是下圖這位:

[圖片]

爲了攻破堅固的特洛伊城,希臘聯軍中的奧德修斯想出了“木馬計”:在木馬腹中藏匿士兵,待特洛伊人將木馬拽入城後,等到夜深人靜時,木馬內的士兵一齊湧出,裏應外合,拿下特洛伊城。

Sinon 則勇敢地擔當了誘使特洛伊人將木馬拖進城的艱鉅任務。他成功地扮演了一名間諜 (Spy) 的角色,憑藉出色的演技使得特洛伊國王堅信,木馬對特洛伊城來說,是個“吉祥物”。

[圖片]

在基於 Sinon 的 SAP UI5 Mock Server 通過 init 方法啓動時,會調用 Sinon.useFakeXMLHttpRequest,將 Sinon 僞造的 FakeXMLHttpRequest 實現,替換 Window 全局的 XMLHttpRequest, 完成了偷天換日。

這個替換,一般的 SAP UI5 開發人員如果不對 Sinon 源代碼進行單步調試,就不會知情。這個情形有點像昔日希臘聯軍的士兵們,藏匿在特洛伊木馬中,神不知鬼不覺地潛入特洛伊城的場景。

[圖片]

[圖片]

值得一提的是,Sinon 的工作原理,和 Java 以及 Angular 裏的 HTTP Intercept(攔截器)是不同的。在 HTTP 攔截器的工作場景中,HTTP 請求在兩個時間點內,可以被框架或者應用開發人員編寫的攔截器處理:

程序代碼調用 API 發送 HTTP 請求後,在 HTTP 請求實際從瀏覽器發出之前,由攔截器進行預處理

應用程序得到遠端的服務器響應後,在交給其回調函數處理之前,由攔截器進行預處理

攔截器對 HTTP 請求的預處理,其類型包括但不侷限於:全局錯誤處理,統一的身份驗證機制,或者增添額外的業務邏輯等等。

而 Sinon 的工作場景下,因爲真實的 XMLHttpRequest 已經被 FakeXMLHttpRequest 替換了,所以根本就沒有真實的 HTTP 請求產生,因此 Chrome 開發者工具 network 標籤頁內也就根本觀察不到任何網絡請求。SAP UI5 應用和 Mock Server 之間的交互,純粹是基於 FakeXMLHttpRequest 在內存中的一問一答而已。

希望本文能夠幫助大家理解 SAP UI5 Mock Server 的使用步驟,工作原理,以及 Mock Server 背後基於的 Sinon 框架的命名由來。

感謝閱讀。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章