理解Moq有困难

本文关键字:Moq 理解 | 更新日期: 2023-09-27 18:29:29

我很难掌握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文章,其中推荐了《.NET中的单元测试与示例的艺术》一书,但这本书很旧,已经绝版了。

理解Moq有困难

对于mocking的一般背景,这个答案很好地解释了它以及为什么您可能想在单元测试中使用它。

具体来说,Moq是一个库,它允许您轻松地创建mock对象并控制它们的行为。它最容易用例子来描述,所以让我们看看你的第一个代码示例:

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类中,以便我们可以配置其行为。

因此,现在我们有了一个mock对象,我们将经常需要配置它对调用其方法的响应方式。这样,我们就可以测试被测系统对它的反应。第2行的Setup方法正是这样做的,它告诉我们的mock对象在用等于"ping"的参数调用DoSomething时返回true。想象一下,你正在使用这个mock来测试下面这样的类:

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;
    }
}

但当你有复杂的逻辑、多个参数或许多依赖关系时,这是一种痛苦;它只是规模不大。这就是mock对象和Moq可以让事情变得容易的地方。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只是一个让使用mock对象变得更容易的库,Quickstart是使用Moq机制的一个很好的参考。这里有几十个嘲讽的教程和指南,只是找一些。记住,直到我开始使用它们,它才真正"点击"我。找到一个编码卡塔,试着自己嘲笑!