代码改变世界

What is “Mock You”系列之(一) 初识Mock 和 Moq

2010-02-21 17:13  姜 萌@cnblogs  阅读(1825)  评论(1编辑  收藏  举报
Moq即Mock You Framework,故名思意是一个类似Mockery,JMock的Mock框架。 是google上的一个.net开源项目
项目扉页 相关下载
http://code.google.com/p/moq/ http://code.google.com/p/moq/downloads/list

先说说一般的使用Mock进行测试的基本过程:

 

image

Moq的3.x版本已经不同以往,这得益于.net3.x为大家带来的Lambda表达式,Linq。

说说Moq的优点:

a.完全开源。开源的好处我就不多说了,不过相比java社区上的活跃,Apache项目的浩繁,.net在这方面确实逊色不少。

b.简单易学,便于使用。Moq的设计原则就是“以极低的门槛获取良好的重构能力”在我个人看来,Moq是我用过的上手最容易使用起来最自然的Mock。

Moq中几个重要的类(在后续文章中详细介绍):

Mock<T>:通过这个类我们能够得到一个Mock<T>对象,T可以是接口 和 类。它有一个公开的Object属性,这个就是我们Moq为我们模拟出的对象。

It:这是一个静态类,用于过滤参数。

MockBehavior:用于配置MockObject的行为,比如是否自动mock。

MockFactory:Mock对象工厂,能够批量生产统一自定义配置的Mock对象,也能批量的进行Mock对象测试。

Match<T>:如果你先嫌It不够用就用Match<T>,通过它能够完全自定义规则。

初识Moq

新建一个测试,我们用三行代码演示一个Moq的使用。

[TestMethod()]
[Owner(wJiang)]
public void MoqTest0()
        {
            //make a Mock Object by Moq
            var mo = new Mock<TargetInterfaceOne>();

            //Setup our Mock Object
            mo.Setup(p => p.MethodWithParamAndResult("abc")).Returns("123");

            //Assert it!
            Assert.AreEqual("123", mo.Object.MethodWithParamAndResult("abc"));
        }

说明:

new Mock<T>返回一个Mock对象,我们可以用var接收,这样写起来更方便些,Mock<T>有一个Object属性,存储的就是我们的模拟对象实例。

Setup的参数是一个Lambda Expression,我们可以理解为:“当 被mock的对象p调用MethodWithParamAndResult方法 并且参数为”abc”的时候”。后面再加一个Return(“123”)我们可以理解为:(在之前Setup的情况下)返回的值为”123”。这样,我们就填充好了一个“伪对象”的行为,我们只让它做一件实事儿:当我们调用mo.Object.MethodWithParaAndResult方法并且参数为”abc”时会返回”123”。

实际上我们不仅能够在Setup后面接Returns方法还能接诸如Throws、Verify之类的方法,这是为什么呢?Setup方法会返回一个ISetup对象,看看ISetup的定义:

public interface ISetup<TMock, TResult> : ICallback<TMock, TResult>, IReturnsThrows<TMock, TResult>, IReturns<TMock, TResult>, IThrows, INever, IVerifies, IHideObjectMembers where TMock : class

恩,是链式编程,ISetup接口继承了很多接口,这里我们注意到IReturns<TMock,TResult>,看看IReturns<TMock, TResult>定义:

public interface IReturns<TMock, TResult> : IHideObjectMembers where TMock : class。

里面有一个方法:IReturnsResult<TMock> Returns<T>(Func<T, TResult> valueFunction);

所以我们还能写出这样的代码:

mo.Setup(p => p.MethodWithParamAndResult("abc"))

.Returns("123")

.Callback(……)

.Throws(……)

.Verifiable(……);

呵呵,这种代码理解起来是很自然的。Moq设计的是不是很人性化呢。