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()
本文转自最课程陆敏技博客园博客,原文链接:http://www.cnblogs.com/luminji/archive/2011/08/15/2136351.html,如需转载请自行联系原作者