使用Moq确定是否调用方法


159

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

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

    internal abstract void SomeOtherMethod();
}

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

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

Answers:


186

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

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。如果未注释,它将通过。


7
这是正确的答案。但是,您必须了解一些内容。您可以模拟不是抽象或虚拟的方法/属性(显然,可以模拟所有接口方法和属性)。

25
-1:.Expect(...)。Verifiable()在此代码中是多余的。使用AAA验证您是否正确。.Verifiable用于.Verify(),即 无参数版本。见stackoverflow.com/questions/980554/...
鲁文Bartelink

@我-是的,可以
reggaeguitar

6

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

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


0

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

因为SomeClassabstract它确实是mockable,但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
reggaeguitar

之所以投票,是因为有时您无法重构,并且需要按
现状
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.