单元测试中,为了让单元测试程序完全脱离外部依赖,需要使用到Mock对象和Stub对象。虽然可以手工编写Mock对象和Stub对象,但通常我们都使用Mocking Framework来帮助我们简单快速的构建需要的Mock对象以及Stub对象。
一、概述
常见的Mocking Framework有如下几种:
1、Rhino Mocks V3.6(2009-9-1)
Rhino Mocks是由Ayende Rahien 开发的一个开源项目,目前版本支持.NET 3.5 & 4.0以及Silverlight的CLR, 采用Castle DynamicProxy方式实现Mock对象的构建。
采用Lambda表达式和泛型以及扩展方法实现调用API的强类型化。
因为实现方式的限制,只能对Interface以及可继承的类进行Mock处理,对于sealed类、非virtual,非抽象以及静态方法则无能为力。
因为考虑与旧版本的兼容性的问题, API较为繁琐,冗余方法较多,学习使用时容易混淆。
被Mvccontrib项目所支持,可以被该项目的TestHelper调用,并用于ASP.NET中Stub对象的模拟。
轻量级应用,不需要被安装,只需要在测试项目中进行引用即可实现对其的调用。
[TestFixture]
public class BrainTests
{
/// <summary>
/// Verify that if hand throws an exception having touched a hot iron, <see cref="IMouth.Yell"/> gets called.
/// </summary>
/// <remarks>
/// Rhino Mocks can mock both interfaces and classes - however, only virtual methods
/// of a class can be mocked (try changing IHand/IMouth to Hand/Mouth).
/// </remarks>
[Test]
public void TouchHotIron_Yell()
{
var hand = MockRepository.GenerateStub<IHand>();
var mouth = MockRepository.GenerateMock<IMouth>();
hand.Stub(h => h.TouchIron(null)).Constraints(Is.Matching<Iron>(i => i.IsHot)).Throw(new BurnException());
mouth.Expect(m => m.Yell());
var brain = new Brain(hand, mouth);
brain.TouchIron(new Iron { IsHot = true });
mouth.VerifyAllExpectations();
}
}
public class BrainTests
{
/// <summary>
/// Verify that if hand throws an exception having touched a hot iron, <see cref="IMouth.Yell"/> gets called.
/// </summary>
/// <remarks>
/// Rhino Mocks can mock both interfaces and classes - however, only virtual methods
/// of a class can be mocked (try changing IHand/IMouth to Hand/Mouth).
/// </remarks>
[Test]
public void TouchHotIron_Yell()
{
var hand = MockRepository.GenerateStub<IHand>();
var mouth = MockRepository.GenerateMock<IMouth>();
hand.Stub(h => h.TouchIron(null)).Constraints(Is.Matching<Iron>(i => i.IsHot)).Throw(new BurnException());
mouth.Expect(m => m.Yell());
var brain = new Brain(hand, mouth);
brain.TouchIron(new Iron { IsHot = true });
mouth.VerifyAllExpectations();
}
}
2、Moq V4.0.10827(2010-8-27)
Moq是一个比较新的开源项目,最早提出了用Lambda表达式和泛型以及扩展方法实现调用API的强类型化,不用通过字符串方式描述Mock对象的方法以及属性,这个特点已经被其他Mocking Framework迅速吸收;