Moq断言一个抽象方法被调用

Jup*_*aol 2 c# unit-testing moq autofixture

我正在使用AutoFixture为我的Abstract类编写单元测试,这是我正在尝试做的代表:

public abstract class Base
{
    public virtual void DoSomethingCool()
    {
        OnDoingSomethingCool();
    }

    protected abstract void OnDoingSomethingCool();
}
Run Code Online (Sandbox Code Playgroud)

我的单元测试看起来像这样:

[TestMethod]
public void TestMethod1()
{
    var fixture = new Fixture().Customize(new AutoMoqCustomization());

    var sut = fixture.Create<Base>();

    // How to assert that the OnDoingSomethingCool method was called
    sut.Invoking(x => x.DoSomethingCool())
        .ShouldNotThrow();
}
Run Code Online (Sandbox Code Playgroud)

那么如何断言受保护的抽象方法实际上是在DoSomethingCool方法中调用的?

如果它是来自注入依赖项的对象,我将能够设置模拟使用Moq并断言该方法被调用,但由于该方法是我的主题测试中的抽象方法,我如何断言该方法被调用?

Jus*_*ony 6

有一堆可以说是这样的:

  1. 看起来你可能要么测试太多,要么对其他实现给予太多控制.

    • (控制太多)通常,如果你想强制从abstract class你的另一个方法调用一个方法,你就不要这样做public virtual.通过这样做,您已经为将来的实现提供了更改此行为的能力.事实上,如果你删除了virtual,那么你可以得到你想要的测试(见下文).我确实提供了一种方法来保持virtual,但再次......不推荐.这是不推荐的,因为你的SUT是你的模拟......这感觉不对.
    • (测试太多)您应该只关心基本行为,而不是实现细节,以免您的测试变得太脆弱.我假设不仅仅是对OnDoingSomethingCool方法的调用,否则你应该把它作为你的主要方法.如果主要行为是这个调用(并且不仅仅是这个调用),那么我将在NotRecommended下面的方法中介绍它.
  2. 您不应该直接测试抽象类.你应该使用Roy Osherove 在单元测试艺术中称为抽象测试类模式的东西.这使得所有实现都可以测试您的行为.然后,您可以传入依赖项.如果你想要那个例子,甚至是抽象测试类模式的简化例子,请告诉我

/

using Moq.Protected;

...

public void NotRecommended_ProbablyTestingTooMuch_BrittleTestBelow
{
    //If you MUST keep DoSomethingCool virtual
    //var baseMock = new Mock<Base>{CallBase = true};
    var baseMock = new Mock<Base>();
    baseMock.Protected().Setup("OnDoingSomethingCool");

    baseMock.Object.DoSomethingCool();

    baseMock.Protected().Verify("OnDoingSomethingCool", Times.AtLeastOnce());
}
Run Code Online (Sandbox Code Playgroud)