使用Moq确定是否调用方法

时间:2008-12-07 17:47:09

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

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

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

    internal abstract void SomeOtherMethod();
}

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

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

3 个答案:

答案 0 :(得分:178)

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

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

如果对该行进行了注释,则在调用Verify时将抛出MockException。如果它被取消注释,它将通过。

答案 1 :(得分:6)

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

您的Someclass构造函数看起来像New(ISomeOtherClass)。然后你会模拟ISomeOtherClass并设置其SomeOtherMethod的期望值并验证期望值。

答案 2 :(得分:-1)

即使我同意@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);