原文地址:Comparing Moq to Rhino Mocks

原文发表时间:Mar 23, 2008

      长期以来我是Rhino Mocks的大粉丝,乐此不疲的写关于它的文章。当Moq出现时,我一直对它无动于衷,因为我原以为lambda表达式是华而不实的。我认为如果它只是使用lambads的话,我对此不感兴趣。

    幸运的是 在我的twitter圈子里有一些人一直对Moq大加赞赏。我是一个乐于承认错误的人,所以我决定找出Moq究竟好在哪里。结果发现,使用lambdas并不是Moq最优的部分。它有清晰干净的API设计以及弱的录制/回放模式.

    为了更好的说明我的意思,这里有一个简单的例子,分别用Rhino Mocks和Moq写的两个单元测试方法。使用mock框架的测试,只用一个方法来建出一个接口。

[Test]

public void RhinoMocksDemoTest()

{

MockRepository mocks = new MockRepository();

var mock = mocks.DynamicMock<ISomethingUseful>();

SetupResult.For(mock.CalculateSomething(0)).IgnoreArguments().Return(1);

mocks.ReplayAll();

var myClass = new MyClass(mock);

Assert.AreEqual(2, myClass.MethodUnderTest(123));

}

[Test]

public void MoqDemoTest()

{

var mock = new Mock<ISomethingUseful>();

mock.Expect(u => u.CalculateSomething(123)).Returns(1);

var myClass = new MyClass(mock.Object);

Assert.AreEqual(2, myClass.MethodUnderTest(123));

}

    注意使用Moq的测试只需要四行代码,而使用Rhino Mocks的测试需要六行。代码的行数当然不是衡量API的标准,但在这个例子中确实是这样。Rhino Mocks中多于的代码是由于需要实例化MockRepository类并调用它的RepalyAll方法。

    我喜欢Moq的另外一个方面是expectations都是基于Mock自身的。即使在我喜欢上它之后,当要使用Rhino Mocks建立results/expecations时,我仍然很困惑。首先你必须使用正确的静态方法,不管是 SetupResult 还是 Expect。第二,我经常搞不清SetupResult.On和SetupResult.For.我感觉MoQ更加直观和清晰。

    我要习惯于Moq的另外一个小的方面是 我一直努力将Mock本身而不是Mock.Object传到需要它的method/ctor上。当你使用Rhino Mocks创建mock的时候,你取回的是实际的类型而不是wrapper.然而,我看到了在Moq方法中使用wrapper的好处,现在非常喜欢用它。

    对Moq的唯一的抱怨 是它的名字。谈论Moq的你必须说“Moq with a Q”.比起MoQ,我更喜欢MonQ.不管如何,如果那是我唯一的抱怨,那我是一个快乐的人!你可以从google Code Page 下载MoQ,了解更多。

Nice work Kzu!

附录

万一你想重建测试例子,以下是我MyClass和接口IsomethingUseful的代码。

public interface ISomethingUseful 
{
int CalculateSomething(int x);
}
public class MyClass
{
public MyClass(ISomethingUseful useful)
{
this.useful = useful;
}
ISomethingUseful useful;
public int MethodUnderTest(int x)
{
//Yah, it's dumb.
return 1 + useful.CalculateSomething(x);
}
}