使用 Moq 确定是不是调用了方法

Posted

技术标签:

【中文标题】使用 Moq 确定是不是调用了方法【英文标题】:Using Moq to determine if a method is called使用 Moq 确定是否调用了方法 【发布时间】:2010-09-25 18:11:20 【问题描述】:

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

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

    internal abstract void SomeOtherMethod();

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

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

【问题讨论】:

【参考方案1】:

您可以通过使用验证来查看您已模拟的事物中的方法是否已被调用,例如:

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

如果该行被留下注释,它会在您调用验证时抛出 MockException。如果未注释,它将通过。

【讨论】:

这是正确答案。然而,你必须明白一些事情。您不能模拟非抽象或虚拟的方法/属性(显然,所有接口方法和属性都可以模拟)。 -1: .Expect(...).Verifiable() 在此代码中是多余的。使用 AAA,您的验证是正确的。 .Verifiable 与 .Verify() 一起使用,即无 arg 版本。见***.com/questions/980554/… @I-- 可以【参考方案2】:

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

您的Someclass 构造函数看起来像New(ISomeOtherClass)。然后,您将模拟 ISomeOtherClass 并在其 SomeOtherMethod 上设置预期以被调用并验证预期。

【讨论】:

【参考方案3】:

尽管我同意@Paul's answer 是推荐的方式,但我只想添加一种由moq 提供的替代方式。

由于SomeClassabstract,它确实是可模拟的,但public void SomeMehod() 不是。关键是要找到模拟方法并以某种方式调用该方法,然后使用CallBase 将调用传播到SomeOtherMethod()。这听起来像是一种 hack,但本质上很简单。如果建议的重构是不可能的,则可以使用它。

// This class is used only for test and purpose is make SomeMethod mockable
public abstract class DummyClass : SomeClass

    public virtual void DummyMethod() => base.SomeMethod();

然后您可以设置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);

【讨论】:

投反对票,因为它更复杂并且需要样板 DummyClass 赞成,因为有时您无法重构,您需要按原样测试实现

以上是关于使用 Moq 确定是不是调用了方法的主要内容,如果未能解决你的问题,请参考以下文章

Moq - 验证除了一个方法之外没有调用任何方法

如何验证在 Moq 中没有调用该方法?

Moq:验证是否调用了一个方法

Moq:设置一个模拟方法在第一次调用时失败,在第二次调用时成功

Moq:验证没有调用方法

使用Moq模拟IList.Add