Demo檔案 : Git傳送門
請參照UnitTest_Day5的Branch
延續昨日的進度,我們將呼叫API的RestSharp獨立出來,並且用依賴介面及外部注入的方式將IRestSharp注入到PTX來達成隔離,並且做到可測試性。
但面臨令一個問題,如果今天開發的是共用套件類的專案,這樣變成要使用物件都必須知道該用什麼東西注入才可使用,這往往會造成使用者困擾,封裝性也不佳,因外部注入的IRestSharp是每個人都可以另外實作的。 甚至更深一層去想,究竟IRestSharp是否需要用Public讓外部使用者都知道有這個東西呢? 是不是反而因為要達到可測試性而讓封裝這件事做得更差?
來看看另一種方式
假設我認為使用這個套件的人只要簡單的建立PTX後即可使用,至於內部如何呼叫API的實作使用者並不需要關心,那麼我們先將IRestSharp從建構子拿掉吧,並且做一個專門產生IRestSharp實體的Factory來滿足需求。
撰寫IRestSharpFactory
1 | /// <summary> |
接著修改原本的PTX.cs
1 | public class PTX |
這邊馬上面臨到一個問題,那我們怎麼Mock IRestSharp,昨天是放在建構子中並透過Nsubstitute來Mock
封裝性變好了,但也變得難以介入模擬外部行為
從IRestSharpFactory著手吧!!
想辦法讓IRestSharpFactory可以讓我們注入Mock的假物件
1 | /// <summary> |
這邊開了一個_IRestSharpForUnitTest屬性,讓外部能夠注入它,接著在Generate的方法中判斷,如果當_IRestSharpForUnitTest不為Null時,直接回傳(通常會特別在這個屬性寫上說明僅供單元測試使用,正常Production Code禁止使用!!)
想辦法在單元測試中注入_IRestSharpForUnitTest
你可能會發現在單元測試中看不到IRestSharpFactory….
原因是我們宣告成Internal,如果要能在專案之外看到就只能開成Public了,但回到最一開始討論的,不就是為了封裝才把他宣告成Internal嗎?如果又改回Public那我們這段工不就白費了,還好還有別的方法可以達成。
告訴UnitTestDay3這個專案,除了它自己之外,還有誰能看到它宣告成Internal的類別與屬性方法
**
讓我們先打開UnitTestDay3**專案的AssemblyInfo
寫下這行
InternalsVisibleTo這邊是要填AssemblyName,透過這個Attribute告訴UnitTestDay3這個專案還有誰能看到它內部的Internal。
而AssemblyName怎麼看呢?在專案上右鍵 > 屬性
如果你有很多單元測試專案需要能看到,InternalsVisibleTo是可以很多組的。
接著在單元測試中就可以看到啦
這樣就達成我們想封裝起來的需求,卻也能讓單元測試進行注入,那今天就談到這吧!!