2016-01-08 122 views
3

我无法抓住Moq框架。从Moq网站他们举这个例子...麻烦理解Moq

// Assumptions: 
public interface IFoo { 
    public bool DoSomething(string); 
    public bool TryParse(string, out string)); 
} 

var mock = new Mock<IFoo>(); 
mock.Setup(foo => foo.DoSomething("ping")).Returns(true); 

什么是Moq设置在这里做?

// out arguments 
var outString = "ack"; 
// TryParse will return true, and the out argument will return "ack", lazy evaluated 
mock.Setup(foo => foo.TryParse("ping", out outString)).Returns(true); 

同样的问题在这里..什么是安装?

有没有人知道Moq的指南可能会更深入?我读了SO post,建议书The Art of Unit Testing with Examples in .NET,但这本书很旧,已经绝版了。

+1

几年前的单元测试艺术[第二版](https://www.manning.com/books/the-art-of-unit-testing-second-edition),这是仍在印刷品AFAIK – NikolaiDante

+0

@NikolaiDante - 哇!甚至没有检查。谢谢! – webworm

回答

4

对于嘲笑的一般背景,this answer做了一个很好的解释它,以及为什么你可能想在你的单元测试中使用它。

具体来说,Moq是一个库,允许您轻松创建模拟对象并控制其行为。这是最简单的举例来形容,让我们看看你的第一个代码示例:

public interface IFoo { 
    public bool DoSomething(string); 
    public bool TryParse(string, out string)); 
} 

/* 1 */ var mock = new Mock<IFoo>(); 
/* 2 */ mock.Setup(foo => foo.DoSomething("ping")).Returns(true); 

1号线创建IFoo接口的模拟实现。在封面下,Moq正在使用Castle DynamicProxy库实时创建IFoo的具体实现,然后将其包装在自己的Mock类中,以便我们可以配置其行为。

所以现在我们有一个模拟对象,我们经常需要配置它如何响应调用它的方法。这样,我们就可以测试我们的系统如何对它做出反应。第2行的Setup方法正是如此,告诉我们的模拟对象返回true,当调用DoSomething时,参数等于"ping"。想象一下,你用这个模拟来测试像下面的类:

public class TestObject 
{ 
    public string TestMethod(IFoo foo) 
    { 
     if (foo.DoSomething("ping")) 
      return "ping"; 
     else if (foo.DoSomething("pong")) 
      return "pong"; 
     return "blah"; 
    } 
} 

要获得完整的测试覆盖率,你想要的IFoo的实现,可:

  1. "ping"回报true在一个测试
  2. "pong"在另一项测试中最后一次测试返回true
  3. 回报false任何参数

可以创建自己的模仿对象有这种行为,例如:

public class MockFoo : IFoo 
{ 
    string trueValue; 

    public MockFoo(string trueValue) 
    { 
     this.trueValue = trueValue; 
    } 

    public bool DoSomething(string value) 
    { 
     return value == trueValue; 
    } 
} 

但是,这是一种当你有复杂的痛苦逻辑,多参数,或一对多的依赖关系;它只是不能很好地扩展。这是模拟对象和Moq可以让事情变得简单的地方。在起订量相同的设置三个测试是:

  1. mock.Setup(foo => foo.DoSomething("ping")).Returns(true); 
    
  2. mock.Setup(foo => foo.DoSomething("pong")).Returns(true); 
    
  3. mock.Setup(foo => foo.DoSomething(It.IsAny<string>())).Returns(false); 
    

在我看来,这是更简单,更表现你期待怎样的IFoo依赖的行为。

至于指南,我认为你最好带着一个嘲笑的指南,而不是一个Moq指定的指南。 Moq只是一个使得使用模拟对象更容易的库,对于使用Moq的机制来说,这是一个很好的参考。有几十个嘲笑教程和指南,只是寻找一些。请记住,它直到我开始使用它时才真正“点击”我。找一个coding kata并尝试自己嘲笑!

+0

优秀的解释!非常感谢您抽出时间把它们放在一起!我会在寻找更一般的“嘲讽”教程时听取您的建议。 – webworm