(一)属性Property
属性也是一种方法。所以对于属性的期望,和方法是一样的。方法和属性的期望在前几篇随笔中已经大量使用。
通常的读或写属性器的期望
public void TestEvent()
{
MockRepository mocks = new MockRepository();
IList < int > _list = mocks.DynamicMock < IList < int >> ();
Expect.Call(_list.Count).Return( 5 );
mocks.ReplayAll();
Assert.AreEqual( 5 , _list.Count);
}
这个是很简单的。然后还有一种自动属性期望的,设置属性行为来达到自动属性期望安装。这个有两种方式,在前边说Mock四种类型时说过:
一是传统的一个一个的安装,还有一种方式就是通过Stub方式实现。
{
int Unid { get ; set ; }
string CustomerName { get ; set ; }
string Address { get ; set ; }
string ShowTitle( string str);
}
这个接口有3个属性。
public void TestProperty()
{
MockRepository mocks = new MockRepository();
var customer = mocks.DynamicMock < ICustomer > ();
using (mocks.Record())
{
Expect.Call(customer.Unid).PropertyBehavior();
Expect.Call(customer.CustomerName).PropertyBehavior();
Expect.Call(customer.Address).PropertyBehavior();
}
customer.Unid = 5 ;
Assert.AreEqual( 5 , customer.Unid);
}
通过这种方法要分别为mock对象设置属性行为。而通过Stub则很简单:
public void TestPropertyStub()
{
MockRepository mocks = new MockRepository();
var customer = mocks.Stub < ICustomer > ();
customer.Unid = 5 ;
Assert.AreEqual( 5 , customer.Unid);
}
通过PropertyBehavior()方法可以为属性模拟行为。这上行为会在模拟对象的生命周期内有效。模拟对象(mock object)与模拟(mock)是两个概念。
(二)方法
属性器有读和写属性,在安装期望时,只是对写属性设置即可。在方法中有多种情况:
(1)无返回值
安装期望:
(2)带返回值
这个前边已经大量使用
安装期望:
(3)带输出参数或引用参数的方法
public void TestOutPara()
{
MockRepository mocks = new MockRepository();
var customer = mocks.DynamicMock < ICustomer > ();
string strOut = " 123 " ;
Expect.Call(customer
.OutParas( "" , out strOut))
.Return( " test " ).OutRef( " xxx " );
mocks.ReplayAll();
customer.OutParas( "" , out strOut);
Assert.AreEqual( " xxx " , strOut);
}
看粗体部分。带输出或引用参数的方法安装期望和正常调用的方式相似。
这里说明一下,RhinoMock3.5支持lambda和3.x扩展属性,所以在安装时可以这样:
这个要结合Action<T>和Func<Tresult>来分析,尤其是Action<T>。
(三)方法选项
可以对安装期望的方法设置选项(options),例如:安装完期望的方法的可调用次数。
设置方法是:Expect.Call或LastCall
这里分别说一下:
(1)Return
当然最长见的就是返回值,为读属性或带返回值的方法返回值设置,与期望匹配。
public void TestMethodOptions()
{
MockRepository mocks = new MockRepository();
var customer = mocks.DynamicMock < ICustomer > ();
using (mocks.Record())
{
Expect.Call(customer.Unid)
.Return( 10 );
}
Assert.AreEqual( 10 , customer.Unid);
}
(2)Throw
异常抛出。
public void TestMethodOptions()
{
MockRepository mocks = new MockRepository();
var customer = mocks.DynamicMock < ICustomer > ();
using (mocks.Record())
{
Expect.Call(customer.ShowTitle( "" ))
.Throw( new Exception( " 不能为空 " ));
}
customer.ShowTitle( "" );
}
结果:failed: System.Exception : 不能为空
(3)方法允许使用的次数
public void TestMethodOptions()
{
MockRepository mocks = new MockRepository();
var customer = mocks.DynamicMock < ICustomer > ();
using (mocks.Record())
{
Expect.Call(customer.ShowTitle( "" ))
.Return( " 不能为空 " )
.Repeat.Once();
}
Assert.AreEqual( " 不能为空 " ,customer.ShowTitle( "" ));
Assert.AreEqual( " 不能为空 " , customer.ShowTitle( "" ));
}
安装期望时,允许调用1次。所以对于两次断言使用,会有异常出现。除了Once,还有Twice(),Any等
(4)忽略方法参数
public void TestMethodOptions()
{
MockRepository mocks = new MockRepository();
var customer = mocks.DynamicMock < ICustomer > ();
using (mocks.Record())
{
Expect.Call(customer.ShowTitle( null ))
.Return( " 不能为空 " )
.IgnoreArguments();
}
Assert.AreEqual( " 不能为空 " , customer.ShowTitle( "" ));
}
请看粗体部分,忽略了字串参数。
(5)简单的自动属性
PropertyBehavior()已经说过,不再赘述