【问题标题】:Verifying if a void method has been called using Moq验证是否使用 Moq 调用了 void 方法
【发布时间】:2016-06-12 17:43:15
【问题描述】:

我有一个班级,负责构建用于导出的 PPT 幻灯片。为了对此进行单元测试,我创建了一个接口,以便可以使用 Moq 进行模拟;到目前为止一切都很好。但是,在尝试测试我的方法是否已被调用时,我遇到了困难。这是一个 void 方法,所以此时我只想知道该方法已被命中。

这是我的界面:

interface IPowerpointExporter
{
    void AddSlides(int amount);

    void setTitle(string title);
}

这是我的单元测试:

[TestMethod]
public void testPPTObject()
{
    var mockPPT = new Mock<IPowerpointExporter>();
    mockPPT.Setup(m => m.AddSlides(1)).Verifiable();
    mockPPT.Object.AddSlides(1);
    mockPPT.VerifyAll();
}

但是,当我打电话给AddSlides() 时,我得到了一个GeneratorException。对此的解释是我的 IPowerpointExporter 无法访问。我有一种感觉,这是因为我试图在接口上调用一个方法,但我不确定,因为此时我的对象位于mockPPT.Object.AddSlides();

请注意,我还尝试了以下尝试使用实际对象而不是 Interface.Object。这也给出了同样的例外:

[TestMethod]
public void testPPTObject()
{
    var mockPPT = new Mock<IPowerpointExporter>();
    mockPPT.Setup(m => m.AddSlides(1)).Verifiable();

    ExportPowerPoint temp = (ExportPowerPoint)mockPPT.Object;
    temp.AddSlides(1);
    mockPPT.VerifyAll();
}

使用 Moq 如何检查我的方法是否已被调用?我在上面做的事情是否正确?

【问题讨论】:

  • 看来你正在测试你的模拟。您应该使用 IPowerpointExporter 测试代码,并验证(模拟)接口上的方法是否被调用

标签: c# unit-testing moq


【解决方案1】:

您可能会遇到该异常,因为您的界面不是 public,或者对 Moq 程序集不可见。请参阅this question 来解决这个问题。

如果这只是帮助您学习起订量的虚拟代码,请不要继续阅读。


但是,如果这是您认为有价值的实际测试,那么您还有其他更基本的问题。在您的第一个示例中,您完全没有做任何事情来测试您的代码!让我们逐行查看:

var mockPPT = new Mock<IPowerpointExporter>();

您创建了 IPowerpointExporter 界面的模拟,到目前为止一切顺利。

mockPPT.Setup(m => m.AddSlides(1)).Verifiable();

您告诉 mock 期望调用它的 AddSlide 方法,参数为 1,并且可以验证该方法。目前没问题。

mockPPT.Object.AddSlides(1);

但这就是它偏离轨道的地方。您只是在模拟上调用该方法,与您在上面设置的方法相同。 Object 属性是一个虚拟对象,它只能做它被设置做的事情并且与你的实际实现没有任何关系

mockPPT.VerifyAll();

现在您已验证您调用了所有可验证的方法。您在此测试中所做的只是验证 Moq 是否有效;您的代码从未被触及。

现在让我们看看第二个示例中的更改代码:

ExportPowerPoint temp = (ExportPowerPoint)mockPPT.Object;
temp.AddSlides(1);

这种转换永远不会起作用。Object 属性只是一些代理(实际上是一种动态类型),由 Moq 生成,它对它所模拟的接口的任何具体实现一无所知。

【讨论】:

  • 为了让自己回到正确的轨道上,我如何测试方法调用是否被命中?只需创建一个 ExportPowerPoint 对象并在其上调用 AddSlides() 方法就足以触发 VerifyAll()?
  • 你的第一个例子会做你想做的事(如果你修复了界面的可见性),但正如我所说,除了学习起订量之外,这对任何其他事情都是毫无价值的测试。
【解决方案2】:

出现此异常是因为 IPowerpointExporter 接口对 Moq 不可访问。

你可以让你的IPowerpointExporter接口public,并且测试完美运行:

public interface IPowerpointExporter
{
    void AddSlides(int amount);

    void setTitle(string title);
}

....

[TestMethod]
public void testPPTObject()
{
    var mockPPT = new Mock<IPowerpointExporter>();
    mockPPT.Setup(m => m.AddSlides(1)).Verifiable();

    ExportPowerPoint temp = (ExportPowerPoint)mockPPT.Object;
    temp.AddSlides(1);
    mockPPT.VerifyAll();
}

但是,当您需要对非公共类型进行测试时,您可以在程序集中使用 InternalsVisibleTo 属性使类型对 Moq 可见。

[assembly:InternalsVisibleTo("DynamicProxyGenAssembly2")]

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-02-26
    • 2010-09-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多