【问题标题】: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() 会被调用。

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

【问题讨论】:

    标签: c# .net unit-testing mocking moq


    【解决方案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 版本。见stackoverflow.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
      • 赞成,因为有时您无法重构,您需要按原样测试实现
      猜你喜欢
      • 2016-06-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-29
      • 2019-05-22
      相关资源
      最近更新 更多