ABP中單元測試的技巧:Mock和數據驅動


(此文章同時發表在本人微信公眾號“dotNET每日精華文章”,歡迎右邊二維碼來關注。)

題記:雖然ABP為大家提供了測試的腳手架了,不過有些小技巧還是需要自己探索的。

ASP.NET Boilerplate(ABP)默認使用的單元測試的框架是xUnit,並且引入了NSubstitute這個便捷的Mock框架。但是有些具體的用法和技巧還是需要自己探索的。下面介紹兩個小技巧。

為AppService注入Mock接口

假設我有一個和釘釘相關的AppService(接口名稱為IDingtalkAppService),這個服務中會調用釘釘的sdk,為了在單元測試的時候避免真實的網絡調用,所以我需要把這部分代碼抽象為一個接口(比如名稱為IDingtalkSdkService)。那么如何把IDingtalkSdkService 模擬注入到IDingtalkAppService中呢?

首先,在TestModule的PreInitialize中添加如下代碼:

//Registering fake services
IocManager.IocContainer.Register(
    Component.For<IAbpZeroDbMigrator>()
        .UsingFactoryMethod(() => Substitute.For<IAbpZeroDbMigrator>())
        .LifestyleSingleton(),
    Component.For<IDingtalkSdkService>()
        .UsingFactoryMethod(() => Substitute.For<IDingtalkSdkService>())
        .LifestyleSingleton()
    );

上面的代碼通過NSubstitute為IDingtalkSdkService注冊一個Mock。在測試類中,還是如ABP的慣例那樣,通過Resolve來獲取IDingtalkAppService的實現。只是在需要給Mock接口的方法設置Returns數據的時候,在測試方法中通過Resolve來現時獲取到此接口的實例。如下:

var sdkService = Resolve<IDingtalkSdkService>();
sdkService.GetAllUserList(null, enterprise).Returns(

這種方式雖然最簡單但有個缺陷,就是必須注冊的時候要求注冊為LifestyleSingleton(單例)。那么如果你依賴的外部接口無法以單例模式運行(這種情況應該極少),那么只有給IDingtalkAppService添加一個IDingtalkSdkService的屬性SdkService,然后把上面的代碼替換為appService.SdkService.GetAllUserList。

NSubstitute使用的更多幫助,請參考其官網:http://nsubstitute.github.io/

數據驅動的單元測試

准確說這不屬於ABP的技巧是xUnit的技巧,只是ABP用到了xUnit,就一並提及。我們的業務邏輯可能會涉及到多個場景或者判斷條件,為了測試每種情況,是為每種情況寫一個測試方法並包含大量的重復代碼,還是使用數據驅動注入測試數據到一個測試方法中,顯然最好的方式是后者。

常見的單元測試框架都提供了數據驅動的支持:

就我的感受而言,xUnit處理數據驅動的方式更為自然。我采用了MemberData的方式來提供數據,就是寫一個返回值為IEnumerable<object[]>的靜態公共方法。

“不廢話,直接上代碼”,大家更能一目了然。示例代碼見:http://git.oschina.net/ike/xbonmpl9wav062rsj71y872.code.git

通過這種方式,我檢查出了一個判斷錯誤,如下圖:

QQ拼音截圖未命名


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM