moq 的常用使用方法(推薦)
Moq,就是Mock you。讀音可以讀成Mock~you。是Mock框架的一種。用于測試中的Mock測試。Mock是模擬的意思。Mock是模擬對象的一種技術。
測試方法
// 準備 Mock IFoo 接口
var mock = new Mock<IFoo>();
// 配置準備模擬的方法,當調用接口中的 DoSomething 方法,并傳遞參數(shù) "bing" 的時候,返回 true
mock.Setup(foo => foo.DoSomething("ping")).Returns(true);
// 方法的參數(shù)中使用了 out 參數(shù)
// out arguments
var outString = "ack";
// 當調用 TryParse 方法的時候,out 參數(shù)返回 "ack", 方法返回 true, lazy evaluated
mock.Setup(foo => foo.TryParse("ping", out outString)).Returns(true);
// ref 參數(shù)
var instance = new Bar();
// 僅僅在使用 ref 調用的時候,才會匹配下面的測試
mock.Setup(foo => foo.Submit(ref instance)).Returns(true);
// 當方法返回值得時候,還可以訪問返回的值
// 這里可以使用多個參數(shù)
mock.Setup(x => x.DoSomething(It.IsAny<string>()))
.Returns((string s) => s.ToLower());
// 在被調用的時候拋出異常
mock.Setup(foo => foo.DoSomething("reset")).Throws<InvalidOperationException>();
mock.Setup(foo => foo.DoSomething("")).Throws(new ArgumentException("command");
// 延遲計算返回的結果
mock.Setup(foo => foo.GetCount()).Returns(() => count);
// 在每一次調用的時候,返回不同的值
var mock = new Mock<IFoo>();
var calls = 0;
mock.Setup(foo => foo.GetCountThing())
.Returns(() => calls)
.Callback(() => calls++);
// 第一次調用返回 0, 下一次是 1, 依次類推
Console.WriteLine(mock.Object.GetCountThing());
匹配參數(shù)
// 任意值
mock.Setup(foo => foo.DoSomething(It.IsAny<string>())).Returns(true);
// 提供的值必須匹配一個函數(shù), lazy evaluated
mock.Setup(foo => foo.Add(It.Is<int>(i => i % 2 == 0))).Returns(true);
// 匹配一個范圍
mock.Setup(foo => foo.Add(It.IsInRange<int>(0, 10, Range.Inclusive))).Returns(true);
// 匹配正則表達式
mock.Setup(x => x.DoSomething(It.IsRegex("[a-d]+", RegexOptions.IgnoreCase))).Returns("foo");
屬性
// 普通屬性
mock.Setup(foo => foo.Name).Returns("bar");
// 多層的屬性
mock.Setup(foo => foo.Bar.Baz.Name).Returns("baz");
// 期望設置屬性的值為 "foo"
mock.SetupSet(foo => foo.Name = "foo");
// 或者直接驗證賦值
mock.VerifySet(foo => foo.Name = "foo");
設置屬性,以便自動跟蹤它的值
// 開始 "tracking" 屬性的 sets/gets
mock.SetupProperty(f => f.Name);
// 提供一個默認的值
mock.SetupProperty(f => f.Name, "foo");
// 現(xiàn)在,你可以:
IFoo foo = mock.Object;
// 保存的值
Assert.Equal("foo", foo.Name);
// 重新設置一個值
foo.Name = "bar";
Assert.Equal("bar", foo.Name);
還可以準備所有的屬性
mock.SetupAllProperties();
事件
// 拋出一個事件
mock.Raise(m => m.FooEvent += null, new FooEventArgs(fooValue));
// 多層的后代中的事件
mock.Raise(m => m.Child.First.FooEvent += null, new FooEventArgs(fooValue));
// 當 Submit 方法被調用的時候,拋出一個事件
mock.Setup(foo => foo.Submit()).Raises(f => f.Sent += null, EventArgs.Empty);
// 拋出異常將會觸發(fā)對象底層的行為
// 你可能需要在后面進行斷言處理
// 拋出一個自定義的事件
public delegate void MyEventHandler(int i, bool b);
public interface IFoo { event MyEventHandler MyEvent; }
var mock = new Mock<IFoo>();
...
// 傳遞自定義的事件參數(shù)
mock.Raise(foo => foo.MyEvent += null, 25, true);
回調
var mock = new Mock<IFoo>();
mock.Setup(foo => foo.Execute("ping"))
.Returns(true)
.Callback(() => calls++);
// 使用調用的參數(shù)
mock.Setup(foo => foo.Execute(It.IsAny<string>()))
.Returns(true)
.Callback((string s) => calls.Add(s));
// 使用泛型語法
mock.Setup(foo => foo.Execute(It.IsAny<string>()))
.Returns(true)
.Callback<string>(s => calls.Add(s));
// 使用多個參數(shù)
mock.Setup(foo => foo.Execute(It.IsAny<int>(), It.IsAny<string>()))
.Returns(true)
.Callback<int, string>((i, s) => calls.Add(s));
// 調用之前和之后的回調
mock.Setup(foo => foo.Execute("ping"))
.Callback(() => Console.WriteLine("Before returns"))
.Returns(true)
.Callback(() => Console.WriteLine("After returns"));
驗證
mock.Verify(foo => foo.Execute("ping"));
// 在驗證失敗的時候,提供自定義的錯誤提示信息
mock.Verify(foo => foo.Execute("ping"), "When doing operation X, the service should be pinged always");
// 從沒有被調用的方法
mock.Verify(foo => foo.Execute("ping"), Times.Never());
// 至少調用過一次
mock.Verify(foo => foo.Execute("ping"), Times.AtLeastOnce());
mock.VerifyGet(foo => foo.Name);
// 驗證對屬性的賦值.
mock.VerifySet(foo => foo.Name);
// 驗證對于屬性設置特定的值
mock.VerifySet(foo => foo.Name ="foo");
// 驗證匹配的參數(shù)
mock.VerifySet(foo => foo.Value = It.IsInRange(1, 5, Range.Inclusive));
自定義 Mock 行為
Mock 的行為分為嚴格的 Strict 和寬松的 Loose, 默認為寬松的。在嚴格模式下,使用任何沒有被指定的行為,都將會拋出異常,寬松模式下,不會拋出任何異常,方法將會返回默認值或者空的數(shù)組等等。
var mock = new Mock<IFoo>(MockBehavior.Strict);
如果沒有重寫基類的實現(xiàn),默認將不會調用基類,在 Mock Web/Html 控件的是必須的。
var mock = new Mock<IFoo> { CallBase = true };
創(chuàng)造自動遞歸的 Mock, Mock 對象對于它的任何成員將會返回一個新的 Mock 對象。
var mock = new Mock<IFoo> { DefaultValue = DefaultValue.Mock };
// 默認是 DefaultValue.Empty
// 現(xiàn)在這個屬性將會返回一個新的 Mock 對象
IBar value = mock.Object.Bar;
// 可以使用返回的 Mock 對象, 后即對屬性的訪問返回相同的對象實例
// 這就允許我們可以進行后繼的設置
// set further expectations on it if we want
var barMock = Mock.Get(value);
barMock.Setup(b => b.Submit()).Returns(true);
中心化的 Mock 實例創(chuàng)建和管理:你可以在一個地方使用 MockRepository 創(chuàng)建和驗證所有的 Mock 對象,設置 MockBehavior, CallBse 和 DefaultValue 約束。
var factory = new MockFactory(MockBehavior.Strict) { DefaultValue = DefaultValue.Mock };
// 創(chuàng)建 Mock 對象
var fooMock = factory.Create<IFoo>();
// 在創(chuàng)建的時候重寫倉庫的設置
var barMock = factory.Create<IBar>(MockBehavior.Loose);
// 驗證通過倉庫創(chuàng)建的對象
factory.Verify();
其它
// 用在測試用例的開始
using Moq.Protected()
// 測試中
var mock = new Mock<CommandBase>(); mock.Protected()
.Setup<int>("Execute")
.Returns(5);
// 如果用到了參數(shù)匹配, 必須使用 ItExpr 來代替 It
// 以后計劃改進
mock.Protected()
.Setup<string>("Execute", ItExpr.IsAny<string>())
.Returns(true);
高級特性
// 從 Mock 實例重新獲得 Mock 對象
IFoo foo = // get mock instance somehow
var fooMock = Mock.Get(foo);
fooMock.Setup(f => f.Submit()).Returns(true);
// 實現(xiàn)多個接口
var foo = new Mock<IFoo>();
var disposableFoo = foo.As<IDisposable>();
// 現(xiàn)在 IFoo mock 已經(jīng)實現(xiàn)了接口 IDisposable :) disposableFoo.Setup(df => df.Dispose());
// 定制匹配
mock.Setup(foo => foo.Submit(IsLarge())).Throws<ArgumentException>(); ...
public string IsLarge()
{
return Match<string>.Create(s => !String.IsNullOrEmpty(s) && s.Length > 100);
}
以上所述是小編給大家介紹的moq 的常用使用方法,希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時回復大家的。在此也非常感謝大家對腳本之家網(wǎng)站的支持!
相關文章
.NET?實現(xiàn)啟動時重定向程序運行路徑及?Windows?服務運行模式部署的方法
這篇文章主要介紹了.NET?實現(xiàn)啟動時重定向程序運行路徑及?Windows?服務運行模式部署,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2022-09-09
ASP.NET Core實現(xiàn)AES-GCM加密算法
這篇文章介紹了ASP.NET Core實現(xiàn)AES-GCM加密的方法,文中通過示例代碼介紹的非常詳細。對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2022-07-07
.NET必知的EventCounters性能指標監(jiān)視器詳解
這篇文章主要介紹了.NET必知的EventCounters性能指標監(jiān)視器,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2020-11-11
ASP.NET?Core?WebApi返回結果統(tǒng)一包裝實踐記錄
本文主要是展示了針對ASP.NET Core WeApi結果統(tǒng)一返回格式的相關操作,通過示例我們一步一步的展示了完成這一目標的不斷升級的實現(xiàn),雖然整體看起來比較簡單,但是卻承載著筆者一次又一次的思考升級2022-04-04
Json數(shù)據(jù)轉換list對象實現(xiàn)思路及代碼
本文為大家詳細介紹下Json數(shù)據(jù)轉換list對象的具體實現(xiàn),感興趣的朋友可以參考下哈,希望對你有所幫助2013-04-04
asp.net中DBNull.Value,null,String.Empty區(qū)別淺析
這篇文章來給大家介紹asp.net中DBNull.Value,null,String.Empty區(qū)別淺析,有需要的同學可以參考一下2013-08-08
asp.net DataFormatString格式化GridView
在GridView里面顯示數(shù)據(jù),要顯示的數(shù)據(jù)有好多位小數(shù),就想讓它只顯示兩位小數(shù),在delphi里,直接用DisplayFormat就行了,2009-08-08

