無接口.NET代碼的單元測試
該工程目前還是VS2010下的C#代碼,雖然大量使用了繼承,封裝和多態,但對接口的應用非常少,所以基本上沒辦法用常見的Mock框架(如Moq, Rhino Mock,等)來寫單元測試。
考慮下來,解決方案無非兩種:一是重構現有代碼,通過接口(interface)來實現依賴注入(Dependency Injection, DI);二是尋找無需通過接口直接支持虛擬實體類的Mock框架,用來攔截對依賴對象的訪問,返回預定的結果。采用方案一的話,優化了代碼架構,從長遠來說更好一些,但是工作量較大,還需要做大量的測試以保證不會改變現有代碼功能。采用方案二的話,則不需要對現有代碼做任何改動,只需要直接創建測試代碼就好了。因此方案二還是很有吸引力的,我就按這個方向做了一些研究。
我發現市面上暫時還沒有開源的Mock框架(.NET單元測試相關)支持虛擬實體類,而收費的我也只找到Microsoft Fakes, TypeMock Isolator和Telerik JustMock這三個。三者雖然用法上有些差異,但是主要功能比較接近,差別主要體現在以下幾個方面:
1.從價格上來看:
Microsoft Fakes,沒有免費版,只有在VS2012/VS2013的Premium和Ultimate版中才能用,而我們的開發環境用的主要是Professional版的,升級到相應版本的話成本很高(VS2013的話Windows Store差價$1770,MSDN Subscription差價$4920)
Telerik JustMock滿足需求的版本價格是每個開發者$399,包含一年免費升級+支持,(參見Buy JustMock)
TypeMock Isolator滿足需求的版本價格是$799每個license,$150每年升級+支持,(參見Isolator Pricing)
由于Fakes價格太高,而且還需要升級現有代碼,我們直接就不考慮了。當然如果已經在用相應版本的話,還是可以考慮的,畢竟微軟自己的東西還是用起來最方便的。
2.從功能上看,根據我們的一個測試用例分別用TypeMock和JustMock試寫了一下,發現JustMock更強大一些。
我們的這個測試用例是要測某個時間值由于特殊原因不包含年份,因此從客戶端傳到位于不同時區的服務端時,在跨年時會被解析到錯誤的年份。比如:客戶端位于GMT+8在2014/01/01 07:00:00時傳了01/01 07:00:00過來,而服務端位于GMT,當時是2013/12/31 23:00:00,這個時間就會被解析成2013/01/01 07:00:00。解析調用的是DateTime.ParseExact()方法。TypeMock對MSCorLib中類的虛擬只提供了有限的支持,不支持這個方法的虛擬。而JustMock在這方面則做得好一些,能夠支持該方法。
所以,我的最終結論是要么重構代碼,使用接口來實現依賴注入,那么基本上各種Mock框架都能用;要么就買JustMock,不用動現有代碼,直接加單元測試就好了。