Mock <>的目的是什么

时间:2018-10-17 16:06:03

标签: c# moq

我继承了一些使用Moq的代码,并在代码中将其实现为:

private Mock<Shape> nativeShape;
private Mock<Document> nativeDoc;
// ...
nativeDoc = new Mock<Microsoft.Office.Interop.Word.Document>();
nativeShape = new Mock<Microsoft.Office.Interop.Word.Shape>();

Git for Moq说明了如何使用它,但未说明其用途以及为什么要使用它。这样做的目的是什么?

2 个答案:

答案 0 :(得分:0)

模拟用于测试用例,尤其是在使用依赖注入的情况下。如果您不熟悉测试驱动开发,我强烈建议您阅读它。 (但这本身就是一个完整的线程。)它允许您创建实现接口或模仿现有类的对象。然后,您可以定义特定测试用例的模拟对象的行为。一个简单的示例是测试依赖于另一个对象的业务对象,例如数据访问层组件。我最近为一个业务对象创建了多个测试,并模拟了DAL。我的测试用例都取决于业务对象如何处理DAL的不同结果(例如,预期数据集,空数据集和异常)。这使我可以自己测试业务逻辑,而无需依赖DAL或数据库。有几种提供模拟功能的库。

答案 1 :(得分:-1)

使用您的示例,假设您有一个对象-称为Foo-在构造函数中需要一个ShapeDocument。在这种情况下,您将有两个选择:

  1. 构建一个实际的Document和一个实际的Shape,但使用测试数据,然后在测试期间将这些对象发送给构造函数。
  2. 仅使用您需要的功能构建一个模拟Document和一个模拟Shape,就可以运行实际实现的测试并将其发送给构造函数以进行测试。

如果您的对象又大又复杂,那么第一个选项可能会变得无法测试,特别是对于大型项目,因为您可能不知道应该如何构造对象或它们是否需要某些参数(例如私钥,指纹等),而您可能无法访问。当您开始使用依赖项注入时,这确实成为一个问题。因此,要解决此问题,您需要接口出需要传递的对象,然后构建模拟实现,以对其进行测试。当然,过一会儿就会变得很重复,这就是Moq存在的原因。

回到示例,您可以像这样测试Foo

public void Foo_TestingFoo_DoesBar()
{
    var mockDoc = new Mock<Document>();
    var mockShape = new Mock<Shape>();

    // "implement" the methods you will need during your test
    mockDoc.Setup(...);
    mockShape.Setup(...);

    // Get the "actual" Document and Shape and use them as arguments to the ctor
    var foo = new Foo(mockDoc.Object, mockShape.Object);

    // Do stuff with foo
    foo.DoBar();

    // Verify that these objects were used how you expected them to be
    mockDoc.Verify(...);
    mockShape.Verify(...);
}