麻豆小视频在线观看_中文黄色一级片_久久久成人精品_成片免费观看视频大全_午夜精品久久久久久久99热浪潮_成人一区二区三区四区

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

隔離框架

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/


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: h视频在线播放 | 久久久久久久久久亚洲精品 | 99国产精品自拍 | 亚州欧美在线 | 97超级碰碰人国产在线观看 | 久久免费视频精品 | 亚洲成人第一区 | 在线观看va | 91综合在线观看 | 亚洲精中文字幕二区三区 | 一级片久久免费 | 黄色毛片视频在线观看 | 欧美一区二区三区不卡免费观看 | 毛片大全在线观看 | 国产外围在线 | 久久久久九九九女人毛片 | 欧美视屏一区二区 | 狠狠干91| 久久久久免费电影 | 久久久久久久久日本理论电影 | 国产资源在线视频 | 欧美性黄 | 国产午夜精品视频免费不卡69堂 | 欧美性黄 | 美女色影院| 亚洲成人入口 | 极品国产91在线网站 | 97伦理| 欧美日韩国产一区二区三区在线观看 | 亚洲第一视频 | 成年免费观看视频 | 久久久久久久91 | 久草在线网址 | 免费a级片视频 | 激情五月少妇a | 国产精品探花在线观看 | 成人做爽爽爽爽免费国产软件 | www.7777在线| 国产乱淫a∨片免费观看 | 欧美另类69xxxxx 视频 | 亚洲一区二区免费 |