MOQ來自于 http://code.google.com/p/moq/
。下載下傳後其實是直接作為DLL被引用的。
Mock是模拟對象的一種技術。
它可以用于以下情況:
----- 真實對象具有不可确定的行為(産生不可預測的結果,如股票的行情)
----- 真實對象很難被建立(比如具體的web容器)
----- 真實對象的某些行為很難觸發(比如網絡錯誤)
----- 真實情況令程式的運作速度很慢
----- 真實對象有使用者界面
----- 測試需要詢問真實對象它是如何被調用的(比如測試可能需要驗證某個回調函數是否被調用了)
----- 真實對象實際上并不存在(當需要和其他開發小組,或者新的硬體系統打交道的時候,這是一個普遍的問題)
1:測試傳回值
需要被測試的代碼:
public interface ICounter
{
int CountArgs(int a, int b);
}
public class SampleClass
{
private ICounter _counter;
public SampleClass(ICounter counter)
{
_counter = counter;
}
public int GetResoult()
{
return _counter.CountArgs(1, 2) + 3;
}
}
測試代碼:
Mock<ICounter> mock = new Mock<ICounter>();
mock.Setup(counter => counter.CountArgs(1, 2)).Returns(3);
SampleClass sample = new SampleClass(mock.Object);
int re = sample.GetResoult();
mock.Verify();
Assert.AreEqual(re, 6);
2:測試抛出異常
假設待測試代碼為:
public interface ICounter
{
int CountArgs(int a, int b);
}
public class SampleClass
{
private ICounter _counter;
public SampleClass(ICounter counter)
{
_counter = counter;
}
public int GetResoult()
{
return _counter.CountArgs(100, 123) + 3;
}
}
測試代碼則為:
Mock<ICounter> mock = new Mock<ICounter>();
mock.Setup(arg => arg.CountArgs(100, 123)).Throws(new ArgumentException("參數過大"));
SampleClass sample = new SampleClass(mock.Object);
try
{
int re = sample.GetResoult();
mock.Verify();
}
catch (ArgumentException)
{
return;
}
Assert.Inconclusive("error");
3:一些限制
MOQ可以直接模拟接口,但是在模拟類的時候,有如下限制:
類不能是密封的;
方法要加上虛修飾符;
不能模拟靜态方法(可以通過擴充卡模式來模拟靜态方法);
其實這些限制中,一般來說我們是不需要模拟類的,但是抽象類還是需要模拟的比較多,比如:
public abstract class CounterBase
{
public abstract int CountArgs(int a, int b);
public int ArgProp { get; set; }
public virtual string GetSomethingVitual()
{
return ArgProp.ToString();
}
public string GetSomethingReal()
{
return "abc";
}
}
public class SampleClass
{
private CounterBase _counter;
public SampleClass(CounterBase counter)
{
_counter = counter;
}
public int GetResult()
{
return _counter.CountArgs(1, 2) + 3;
}
public string GetVitual()
{
return _counter.GetSomethingVitual();
}
public string GetReal()
{
return _counter.GetSomethingReal();
}
}
在這裡,作為調用者SampleClass來說,由于使用到了CounterBase,是以CounterBase 這個抽象類就是有必要被模拟的。SampleClass示範了調用抽象方法、虛方法、普通方法,運作的結果是:
------ Test started: Assembly: TestProject1.dll ------
Test 'TestProject1.ProgramTest.TestReal' failed: Test method TestProject1.ProgramTest.TestReal threw exception:
System.NotSupportedException: Invalid setup on a non-virtual (overridable in VB) member: arg => arg.GetSomethingReal()
at Moq.Mock.ThrowIfCantOverride(Expression setup, MethodInfo method)
at Moq.Mock.<>c__DisplayClass1c`2.<Setup>b__1b()
at Moq.PexProtector.Invoke[T](Func`1 function)
at Moq.Mock.Setup[T,TResult](Mock mock, Expression`1 expression, Func`1 condition)
at Moq.Mock`1.Setup[TResult](Expression`1 expression)
ProgramTest.cs(101,0): at TestProject1.ProgramTest.TestReal()
2 passed, 1 failed, 0 skipped, took 1.32 seconds (MSTest 10.0).
我們可以看到,前面兩個方法都成功,隻有那個非虛拟的普通方法失敗,資訊如下:
Invalid setup on a non-virtual (overridable in VB) member: arg => arg.GetSomethingReal()
![](https://img.laitimes.com/img/_0nNw4CM6IyYiwiM6ICdiwiIn5GcuEDZ2MTOmFjZlNDZhNTY1UmN0MTM3YGMjJTYwUWY0ITOfdWbp9CXt92Yu4GZjlGbh5SZslmZxl3Lc9CX6MHc0RHaiojIsJye.png)
本篇代碼下載下傳:
ConsoleApplication20110812.rar本文基于
Creative Commons Attribution 2.5 China Mainland License釋出,歡迎轉載,演繹或用于商業目的,但是必須保留本文的署名
http://www.cnblogs.com/luminji(包含連結)。如您有任何疑問或者授權方面的協商,請給我留言。