亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 學院 > 開發設計 > 正文

隔離框架

2019-11-14 14:33:30
字體:
來源:轉載
供稿:網友

  前面說了手工創建模擬對象的示例,這一章主要說一下使用模擬框架創建示例。我使用的模擬框架是NSubstitute

1:如何創建偽對象

我們知道手動編寫偽對象顯得很笨拙(當然按照實際情況),那么用隔離框架創建偽對象就會很簡單快速,那么我們先看一幅圖

那么首先我們創建一個個接口

1  public interface IUser2     {3         bool Add(string userName, string realName);4     }
IUser

實現接口

1 public class User:IUser {2         public bool Add(string userName, string realName)3         {4             return true;5         }6     }
User

業務中調用

 1 public class UserManager 2     { 3         public bool Add(string userName, string realName) 4         { 5             if (string.IsNullOrWhiteSpace(userName))throw new ArgumentNullException(userName); 6             if (string.IsNullOrWhiteSpace(realName)) throw new ArgumentNullException(realName); 7  8             if (userName.Length>=0) 9             {10                 return false;11             }12             return GetUser().Add(userName, realName);13         }14 }
UserManager

單元測試

1                 [Test]2         public void Add_Default_CallAdd()3         {4             var fakeUser = Substitute.For<IUser>();5             fakeUser.Add("1", "1").Returns(true);//按照我們的意愿進行返回值            6             Assert.IsTrue(fakeUser.Add("1", "1"));                7         }
Add_Default_CallAdd()

以上是我們輸入2個參數然后按我們意愿返回true;

如果我們不考慮參數呢

那么只需要把參數置為Arg.Any<T>()//T表示參數的類型可以string,int等看下測試結果

 當然返回值一定是按照你預定的類型。比喻bool Add() 返回值必須是一個bool類型的或者拋出異常。

2:When...Do的用法

when do在NSub的用處還是比較廣的。比喻當什么的時候做什么。下面一個例子來看一下

1 [Test]2         public void Add_Default_CallAdd()3         {4             var fakeUser = Substitute.For<IUser>();            5             fakeUser.When(x => x.Add("1", "2")).6                 Do(content => { throw new Exception("fack exception"); });//用when,do表示式,表示當操作這個函數的時候會出現什么后果        7             Assert.Throws<Exception>(() => fakeUser.Add("1","2"));        8         }
When-Do

上面的例子就是當參數是1和2的時候會拋出一個異常。下面看現實的結果

剛剛參數是1和2會拋出一個異常如果是1和3會不會拋出異常呢,我們手動把參數進行修改在看下面效果

我們一看測試通不過,此時說明只有當參數1和2的時候才會拋出異常這樣一來模擬框架也會給我們預定的參數進行一個驗證。

3:很強大的Received()

Received()方法工作很神奇,這個方法在什么對象被調用就會返回和這個對象同樣類型的對象,但實際上就是申明斷言的對象。什么意思呢我們看下面的代碼
測試中的接口和實現方法參考上一篇

 1 [Test] 2         public void RecordLog_EmailServiceThrows_CallEmail() 3         { 4             var stub = Substitute.For<ILogService>(); 5             var mock = Substitute.For<IEmailService>(); 6             stub.When(p => p.ErrorLog(Arg.Any<String>())).Do(a => { throw new ArgumentNullException(); }); 7             var test = new TestUserManager(stub, mock); 8             test.RecordLog("");//觸發             9             mock.Received().SendEmail(Arg.Is("lp"), Arg.Is("subject"), Arg.Is("值不能為 null。"));//保證接受了方法并調用(不可以少一個句號)            10         }
測試

在以上的例子我們可以看出Received()就表示SendEmail被調用并且收獲到SendEmail發送的信息然后進行斷言是否和預定發送的信息保持一致。這個和上一篇說的模擬對象斷言是一樣的。(如果使用模擬對象不要忘記Received)

4:事件應該怎么測試

  •  測試監聽事件的一方
  •  測試觸發事件的一方

4.1:測試監聽事件

定義一個事件的接口

1 public interface IView2     {3         event Action Loaded;4         void Render(string content);5     }
IView

事件相關的代碼并如何觸發事件的

 1 public class PResenter 2     { 3  4         private readonly IView _view; 5  6         public Presenter(IView view) 7         { 8             this._view = view; 9             this._view.Loaded += Onload;//注冊事件10         }11 12         public void Onload()13         {14             _view.Render("Hello World");15         }16     }
Presenter

測試代碼

 1 [Test] 2         public void Ctor_WhenViewIsLoad_CallsViewRender() 3         { 4             var mockView = Substitute.For<IView>(); 5             var p =new Presenter(mockView); 6             mockView.Loaded += Raise.Event<Action>(); 7  8             mockView.Received().Render(Arg.Is<string>(s=>s.Contains("Hello World"))); 9 10         }
Ctor_WhenViewIsLoad_CallsViewRender

Raise.Event表示觸發事件。

最后使用received來測試是否view中的Render是否觸發,如果真的觸發那么接受的參數是否是Hello World。

我們可以模擬一個存根一個一個模擬對象

修改與事件相關的代碼

 1 public class Presenter 2     { 3  4         private readonly IView _view; 5         private readonly ILogService _logService; 6  7         public Presenter(IView view,ILogService logService) 8         { 9             this._view = view;10             this._logService = logService;11             this._view.Loaded += Onload;//注冊事件12             this._view.ErrorOccured += WriteLog;13         }14 15         public void Onload()16         {17             _view.Render("Hello World");18         }19 20         public void WriteLog(string errorContent) {21             _logService.ErrorLog(errorContent);22         }23     }
Presenter

測試代碼

 1     [Test] 2         public void Ctor_WhenViewIsError_CallsLogs() { 3  4             var stubView = Substitute.For<IView>(); 5             var mockLog = Substitute.For<ILogService>(); 6             var p = new Presenter(stubView,mockLog); 7             stubView.ErrorOccured += Raise.Event<Action<string>>("fack error"); 8             mockLog.Received().ErrorLog(Arg.Is<string>(s => s.Contains("fack error"))); 9 10         }
Ctor_WhenViewIsError_CallsLogs

注意:使用存根stubView.ErrorOccured += Raise.Event<Action<string>>("fack error");來觸發事件,然后在用模擬對象查看日志服務是否被正確的調用

4.2:測試事件是否觸發

這個比較簡單,在測試方法內部使用一個匿名委托,手動注冊次方法即可

定義一個變量,當事件觸發改變變量的值即可。

如:bool isTrigger=false;

SomeView=new SomeView();

SomeView.Load+=delegate{isTrigger=true;}

SomeView.觸發事件 然后比對isTrigger的值是否改變。

5:模擬框架的優缺點

  • 優點
    • 容易驗證參數
    • 容易創建偽對象
    • 使用模擬對象的時候比較簡單不用手寫大量代碼
  • 缺點

         測試代碼不可讀

         驗證錯誤的事情

        一個測試可能會有多個模擬對象

       過度指定

NSubstitute的官方文檔很詳細有興趣的可以自己查看動手寫一寫會有更好的效果http://nsubstitute.github.io/help/raising-events/


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
亚洲最大成人在线| 91免费福利视频| 美日韩在线视频| 欧洲一区二区视频| 日韩高清有码在线| 欧美午夜精品久久久久久浪潮| 亚洲国产欧美一区二区丝袜黑人| 亚洲欧洲激情在线| 亚洲精品一区久久久久久| 亚洲综合日韩中文字幕v在线| 伊人久久精品视频| 欧美午夜www高清视频| 欧美激情欧美激情| 色诱女教师一区二区三区| 日韩成人在线视频| 日韩暖暖在线视频| 久久久久久久影视| 欧美综合在线观看| 亚洲国产精品久久久| 欧美乱妇高清无乱码| 久久久久久网站| 成人在线精品视频| 91精品国产99久久久久久| 日韩欧美精品网站| 久久手机精品视频| 8x拔播拔播x8国产精品| 亚洲成色777777在线观看影院| 91精品国产高清自在线看超| 亚洲午夜精品视频| 国产日韩欧美另类| 精品久久久久久中文字幕大豆网| 亚洲欧洲日韩国产| 亚洲人成网站999久久久综合| 亚洲欧洲美洲在线综合| 久久久天堂国产精品女人| 91亚洲精品久久久久久久久久久久| 久久免费视频这里只有精品| 国产精品综合网站| 色综合色综合网色综合| 91九色国产在线| 性欧美激情精品| 国产精品爽黄69| 久久精品影视伊人网| 98午夜经典影视| 国产精品美女在线| 久久天天躁狠狠躁夜夜躁2014| 国产亚洲精品美女| 亚洲美女黄色片| 精品伊人久久97| 亚洲电影免费在线观看| 蜜月aⅴ免费一区二区三区| 亚洲精品短视频| 情事1991在线| 日韩av三级在线观看| 日本在线观看天堂男亚洲| 欧美视频中文在线看| 亚洲精品视频网上网址在线观看| 欧美激情中文网| 欧美激情一级欧美精品| 欧美视频13p| 亚洲字幕在线观看| 国产精品老牛影院在线观看| 在线看片第一页欧美| 久久综合色影院| 亚洲精品美女久久| 欧美日韩福利在线观看| 成人网在线免费观看| 午夜精品久久久久久久99热浪潮| 国模精品视频一区二区三区| 亚洲国产成人久久综合| 91精品国产高清久久久久久| 亚洲欧洲午夜一线一品| 欧美午夜性色大片在线观看| 一本大道香蕉久在线播放29| 福利视频导航一区| 一本一本久久a久久精品综合小说| 中文亚洲视频在线| 久久精品国产清自在天天线| 欧美国产激情18| 中文字幕自拍vr一区二区三区| 成人性生交xxxxx网站| 国产精品中文字幕在线| 4p变态网欧美系列| 国产在线a不卡| 国自在线精品视频| 色哟哟网站入口亚洲精品| 97久久国产精品| 亚洲国内高清视频| 国产又爽又黄的激情精品视频| 亚洲国产精品女人久久久| 欧美精品久久久久久久久久| 欧美一级成年大片在线观看| 成人国产在线激情| 国产性猛交xxxx免费看久久| 成人免费视频97| 亚洲一级黄色片| 91在线免费视频| 国产欧美一区二区三区久久人妖| 在线观看欧美日韩国产| 日韩欧美精品在线观看| 亚洲毛片在线免费观看| 少妇高潮久久久久久潘金莲| 日韩成人中文字幕在线观看| 亚洲美女免费精品视频在线观看| 国产精品视频自在线| 国产99久久久欧美黑人| 91色中文字幕| 成人在线视频福利| 亚洲在线视频观看| 国产精品成人va在线观看| 亚洲摸下面视频| 亚洲精品美女久久久| 成人精品视频99在线观看免费| 国产精品久久久久不卡| 91精品久久久久久久久久久| 久热国产精品视频| 亚洲春色另类小说| 国产精品 欧美在线| 3344国产精品免费看| 国产欧美一区二区三区在线| 精品久久久久久中文字幕大豆网| 成人激情视频在线播放| 91高清免费视频| www.日韩欧美| 性欧美xxxx交| 疯狂蹂躏欧美一区二区精品| 日韩av在线播放资源| 91久久国产婷婷一区二区| 成人黄在线观看| 欧美黑人xxx| 欧美日韩亚洲精品一区二区三区| 精品免费在线观看| 日韩毛片在线看| 热久久美女精品天天吊色| 亚洲成人在线网| 久久精品99久久香蕉国产色戒| 韩国19禁主播vip福利视频| 国产亚洲精品美女久久久| 久久精品国产久精国产一老狼| 国产日韩综合一区二区性色av| 一色桃子一区二区| 午夜精品久久久久久久99热浪潮| 国内精品视频久久| 国产精品美乳在线观看| 性金发美女69hd大尺寸| 国产精品狠色婷| 日韩中文理论片| 亚洲精品久久久久中文字幕欢迎你| 欧美精品免费播放| 97欧美精品一区二区三区| 欧美日韩成人免费| 亚洲高清免费观看高清完整版| 日韩的一区二区| 欧美在线不卡区| 欧美麻豆久久久久久中文| 日韩精品中文字| 欧美激情视频网| 日本韩国在线不卡| 欧美日本高清一区| 日韩有码片在线观看| 91免费观看网站| 国产精品第一页在线| 韩国视频理论视频久久| 国产日韩欧美在线播放|