使用 Moq 确定方法是否被调用

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/347818/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-04 00:03:07  来源:igfitidea点击:

Using Moq to determine if a method is called

c#.netunit-testingmockingmoq

提问by Owen

It is my understanding that I can test that a method call will occur if I call a higher level method, i.e.:

我的理解是,如果我调用更高级别的方法,我可以测试是否会发生方法调用,即:

public abstract class SomeClass()
{    
    public void SomeMehod()
    {
        SomeOtherMethod();
    }

    internal abstract void SomeOtherMethod();
}

I want to test that if I call SomeMethod()then I expect that SomeOtherMethod()will be called.

我想测试一下,如果我打电话,SomeMethod()那么我希望SomeOtherMethod()会被调用。

Am I right in thinking this sort of test is available in a mocking framework?

我认为这种测试在模拟框架中可用是否正确?

采纳答案by Paul

You can see if a method in something you have mocked has been called by using Verify, e.g.:

您可以使用验证查看您模拟的某个方法是否已被调用,例如:

static void Main(string[] args)
{
        Mock<ITest> mock = new Mock<ITest>();

        ClassBeingTested testedClass = new ClassBeingTested();
        testedClass.WorkMethod(mock.Object);

        mock.Verify(m => m.MethodToCheckIfCalled());
}

class ClassBeingTested
{
    public void WorkMethod(ITest test)
    {
        //test.MethodToCheckIfCalled();
    }
}

public interface ITest
{
    void MethodToCheckIfCalled();
}

If the line is left commented it will throw a MockException when you call Verify. If it is uncommented it will pass.

如果该行被保留注释,则在调用验证时它将抛出 MockException。如果取消注释,它将通过。

回答by Val

No, mock testing assumes you are using certain testable design patterns, one of which is injection. In your case you would be testing SomeClass.SomeMethodand SomeOtherMethodmust be implemented in another entity which needs to be interfaced.

不,模拟测试假定您正在使用某些可测试的设计模式,其中之一是注入。在您的情况下,您将进行测试SomeClass.SomeMethod并且SomeOtherMethod必须在需要连接的另一个实体中实现。

Your Someclassconstructor would look like New(ISomeOtherClass). Then you would mock the ISomeOtherClassand set expectation on its SomeOtherMethodto be called and verify the expectation.

你的Someclass构造函数看起来像New(ISomeOtherClass). 然后,您将模拟ISomeOtherClass并设置对其SomeOtherMethod调用的期望并验证期望。

回答by Johnny

Even though I agree that the @Paul's answeris the recommended way to go I just want to add one alternative way which is provided by moqoff the self.

尽管我同意@Paul 的答案是推荐的方法,但我只想添加一种由moq自我提供的替代方法。

Since SomeClassis abstractit is indeed mockable, but public void SomeMehod()isn't. The point is to find the way to mock and somehow invoke that method and then using CallBasepropagate the call to the SomeOtherMethod(). It might sound as a hack but it is simple in essence. It could be used in the case if the proposed refactoring is not possible.

因为SomeClassabstract它确实是mockable,但public void SomeMehod()并非如此。关键是找到模拟并以某种方式调用该方法的方法,然后使用CallBase将调用传播到SomeOtherMethod(). 这可能听起来像黑客,但本质上很简单。如果建议的重构不可能,它可以用于这种情况。

// This class is used only for test and purpose is make SomeMethod mockable
public abstract class DummyClass : SomeClass
{
    public virtual void DummyMethod() => base.SomeMethod();
}

Then you could setup DummyMethod()to propagate the call by setting CallBaseflag.

然后你可以设置DummyMethod()通过设置CallBase标志来传播调用。

//Arrange
var mock = new Mock<DummyClass>();
mock.Setup(m => m.DummyMethod()).CallBase();

//Act
mock.Object.SomeMethod();

//Assert
mock.Verify(m => m.SomeOtherMethod(), Times.Once);