简体   繁体   English

验证是否已使用Moq调用了void方法

[英]Verifying if a void method has been called using Moq

I have a class which is responsible for building PPT slides for exporting. 我有一堂课,负责构建要导出的PPT幻灯片。 To unit test this I have created an interface so it can be mocking using Moq; 为了对此进行单元测试,我创建了一个接口,以便可以使用Moq进行模拟; all great so far. 到目前为止一切都很好。 However I run into difficulties when trying to test that my method has been called. 但是,在尝试测试我的方法已被调用时遇到了困难。 It is a void method so at this point I only want to know that the method has been hit. 这是一个无效方法,因此在这一点上我只想知道该方法已被执行。

Here is my interface: 这是我的界面:

interface IPowerpointExporter
{
    void AddSlides(int amount);

    void setTitle(string title);
}

And here's my unit test: 这是我的单元测试:

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

However when I come to call AddSlides() I get a GeneratorException . 但是,当我打电话给AddSlides()我得到了GeneratorException The explanation for this is that my IPowerpointExporter was not accessible. 原因是无法访问我的IPowerpointExporter。 I have a feeling this is because I am trying to call a method on an interface, though I'm unsure since I've got my object at mockPPT.Object.AddSlides(); 我有一种感觉,这是因为我正在尝试在接口上调用方法,尽管我不确定,因为我的对象位于mockPPT.Object.AddSlides(); at this point. 这一点。

Note that I've also tried the following trying to use an actual object rather than Interface.Object. 请注意,我还尝试了以下尝试使用实际对象而不是Interface.Object的方法。 This also gives the same exception: 这也给出了相同的例外:

[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();
}

Using Moq how can I check that my method has been called? 使用Moq,如何检查我的方法已被调用? Is what I'm doing above along the right lines? 我在上面按照正确的方法做的吗?

You're likely getting that exception because your interface is not public , or otherwise visible to the Moq assembly. 您可能会收到该异常,因为您的界面不是public ,或者对于Moq程序集是可见的。 See this question to resolve that. 看到这个问题来解决。

If this is just dummy code to help you learn Moq, then read no further. 如果这只是帮助您学习Moq的伪代码,请不要继续阅读。


However, if this an actual test that you think has value, then you have other more fundamental issues. 但是,如果您认为此实际测试有价值,那么您还将遇到其他更基本的问题。 In your first example, you're doing absolutely nothing to test your code! 在第一个示例中, 您绝对没有做任何事情来测试您的代码! Let's go through it, line by line: 让我们逐行浏览一下:

var mockPPT = new Mock<IPowerpointExporter>();

You created a mock of your IPowerpointExporter interface, so far so good. 到目前为止,您IPowerpointExporter创建了IPowerpointExporter接口的模拟。

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

You told the mock to expect a call to it's AddSlide method, with an argument of 1 , and that the method can be verified. 您告诉该模拟程序期望对其参数为1AddSlide方法进行调用,并且可以验证该方法。 No problem so far. 到目前为止没有问题。

mockPPT.Object.AddSlides(1);

But here's where it goes off the rails. 但是,这就是偏离轨道的地方。 You're just invoking the method on your mock, the same one you just setup above. 您只是在调用模拟中的方法,就像上面刚刚设置的方法一样。 The Object property is a dummy object , it can only do what it was setup to do and has no ties to your actual implementation ! Object属性是一个虚拟对象 ,它只能执行设置时要执行的操作, 并且与您的实际实现没有关系

mockPPT.VerifyAll();

Now you verified that you called all your verifiable methods. 现在,您已验证已调用所有可验证的方法。 All you did in this test was verify that Moq works; 您在此测试中所做的全部工作就是验证Moq是否有效; your code was never touched. 您的代码从未被触及过。

Let's look at the changed code in your second example now: 现在让我们在第二个示例中查看更改后的代码:

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

That cast will never work. 该演员将永远无法工作。 The Object property is just some proxy (a dynamic type actually), generated by Moq that knows nothing about any concrete implementation of the interface it is mocking. Object属性只是Moq生成的某种代理(实际上是一种动态类型),对该代理所模拟的接口的任何具体实现一无所知。

This exception occurs because IPowerpointExporter interface is not accessible to Moq. 发生此异常的原因是Moq无法访问IPowerpointExporter接口。

You can make your IPowerpointExporter interface public , and test runs perfectly: 您可以将IPowerpointExporter接口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();
}

However, when you need make tests to non-public types, you can use InternalsVisibleTo attribute in your assembly to make types visible to Moq. 但是,当需要对非公共类型进行测试时,可以在程序集中使用InternalsVisibleTo属性使Moq可以看到类型。

[assembly:InternalsVisibleTo("DynamicProxyGenAssembly2")]

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM