MockRespository有四种泛型方法:
·CreateMock<T>
·CreateDynamicMock<T>
·PartialMock
·Stub
在3.5中,三种已经过时的方法分别由以下方法替代:
·StrictMock<T>
·DynamicMock<T>
·PartialMock<T>
·Stub<T>
它们各自对应静态工厂方法:
·MockRepository.GenerateStrictMock<T>
·MockRepository.GenerateMock
·MockRepository.GeneratePartialMock<T>
·MockRepository.GenerateStub<T>
(1)StrictMock
通过这个方法可以创建一个具有严格语义的T类型mock对象,如果在使用过程中没有显式的对过程进行录制,则会出错误,并会抛出异常。
例如:
public void TestStrictMock()
{
MockRepository mocks = new MockRepository();
ICustomer customer = mocks.StrictMock < ICustomer > ();
customer.Replay();
customer.ShowTitle( "" );
mocks.VerifyAll();
}
这里没有对customer的ShowTitle方法显式地安装期望, 而mock对象又是具有严格语义的对象,所以这里会发生错误,而抛出异常。
(2)DynamicMock
通过这个方法可以创建一个具有动态语义的T类型mock对象,如果在使用过种中没有显式的对过程进行录制,则不会出现异常。如果方法有返回值,那么会返回null或0。
同样以上个例子来说:
{
MockRepository mocks = new MockRepository();
ICustomer customer = mocks.DynamicMock < ICustomer > ();
customer.Replay();
customer.ShowTitle( "" );
mocks.VerifyAll();
}
这里同样没有进行显式的安装期望,但不会出现错误,不会抛出异常。所以当使用动态语义模拟对象时,没有显式安装期望的方法会被忽略。
(3)PartialMock
可以模拟类的一部分。可以独立测试抽象方法。它只能用于类。加一官方描述的话:如果方法上没有设置期望的值,就从一个调用类方法的默认类上去创建一个Mock对象。
现在用例子来说明一下,这个例子通过抽象类来进行,抽象类中有一模板方法,而其中的方法是个抽象的,这里通过官网提供的例子来进行:
{
public int Register;
public virtual int Inc()
{
Register = Add( 1 );
return Register;
}
public abstract int Add( int i);
}
public void TestPartialMock()
{
MockRepository mocks = new MockRepository();
ProcessorBase proc = mocks.PartialMock < ProcessorBase > ();
using (mocks.Record())
{
Expect.Call(proc.Add( 1 )).Return( 1 );
Expect.Call(proc.Add( 1 )).Return( 2 );
}
proc.Inc();
Assert.AreEqual( 1 , proc.Register);
proc.Inc();
Assert.AreEqual( 2 , proc.Register);
mocks.VerifyAll();
}
(4)Stub
直接以例子进行
{
int Legs { get ; set ; }
int Eyes { get ; set ; }
string Name { get ; set ; }
string Species { get ; set ; }
event EventHandler Hungry;
string GetMood();
}
public class AnimalTest
{
IAnimal _animal;
public AnimalTest(IAnimal animal)
{
_animal = animal;
}
public void SetLegs( int count)
{
_animal.Legs = count;
}
}
测试:
public void CreateAnimalStub()
{
MockRepository mocks = new MockRepository();
IAnimal animal = mocks.DynamicMock < IAnimal > ();
Expect.Call(animal.Legs).PropertyBehavior();
Expect.Call(animal.Eyes).PropertyBehavior();
Expect.Call(animal.Name).PropertyBehavior();
Expect.Call(animal.Species).PropertyBehavior();
AnimalTest aa = new AnimalTest(animal);
aa.SetLegs( 10 );
Assert.AreEqual( 10 , animal.Legs);
}
设置接口属性行为,可以在实例中使用。这个属性行为可以通过Stub来设置,那就简单了:
public void CreateAnimalStub()
{
MockRepository mocks = new MockRepository();
IAnimal animal = mocks.Stub < IAnimal > ();
AnimalTest aa = new AnimalTest(animal);
aa.SetLegs( 10 );
Assert.AreEqual( 10 , animal.Legs);
}
当然,也可利用反射来封装对象属性行为设置mock对象的所有属性:
{
PropertyInfo[] properties = mock.GetType().GetProperties();
foreach (PropertyInfo property in properties)
{
if (property.CanRead && property.CanWrite)
{
property.GetValue(mock, null );
LastCall.On(mock).PropertyBehavior();
}
}
}
从这里看出Stub是多么的方便。