Dependency Injection - Extract Dependency Object
External Dependency 是系統中與被測試程式互動但你無法控制的物件。被測試程式受到 external dependency 行為影響可能有不同結果,為了保持 unit test 穩定,不會一下結果該是 A、一下結果該是 B,我們希望能掌控 external dependency──藉由 stub object 模擬 external dependency 的行為並將其 inject 到被測試程式中,基本步驟如下:
- 抽出 external dependency object 的 interface
- stub implement 該 interface 並實作 function
- inject stub 到被測試程式
- Constructor Injection
- Setter Injection
- Extract and Override
本篇用例子說明步驟 1 跟 2:MyClass
是被測試程式,Foo
是 external dependency。(為了讓 code 短一點直接在 header 實作)
1 |
|
1 |
|
首先幫 external dependency Foo
加 interface(C++ 沒有 interface
所以用所有 function 都是 pure virtual function 的 class 當 interface):
1 |
|
1 |
|
被測試程式 MyClass
原本直接使用 Foo
的地方改用 interface:
1 |
|
接下來寫個假 class 實作 IFoo
,實作相關 function 回傳假資料。
這個 class 可以以 Fake
開頭命名,表示它是類似某個 class 的假 class。以 Fake
開頭的 class 產生的 object 可以當作 stub 或 mock 使用。
1 |
|
這邊的例子是 C++,必須 extract interface。在非 strong type 語言,例如 PHP,如果原本 production code 的 dependency object 沒有 interface、只有 unit test 需要的時候,我會偷懶不 extract interface(喂),只讓 fake class 跟原本 class 有一樣 function,甚至只有 test case 會用到的 function。
有 fake class 後利用 dependency injection 將 stub object inject 進被測試程式,我們就能控制被測試程式的 external dependency,進而控制 test case 及預期被測試程式應有的行為。
以上是 dependency injection 的前置作業,那我們下回見~(咦)