C# Moq断言调用一个抽象方法

C# Moq断言调用一个抽象方法,c#,unit-testing,moq,autofixture,C#,Unit Testing,Moq,Autofixture,我正在使用AutoFixture为我的抽象类编写一个单元测试,这是我试图做的一个表示: public abstract class Base { public virtual void DoSomethingCool() { OnDoingSomethingCool(); } protected abstract void OnDoingSomethingCool(); } 我的单元测试如下所示: [TestMethod] public voi

我正在使用AutoFixture为我的抽象类编写一个单元测试,这是我试图做的一个表示:

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

    protected abstract void OnDoingSomethingCool();
}
我的单元测试如下所示:

[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();
}
[TestMethod]
公共void TestMethod1()
{
var fixture=new fixture().Customize(new AutoMoqCustomization());
var sut=fixture.Create();
//如何断言调用了OnDoingSomethingTool方法
sut.Invoking(x=>x.DoSomethingCool())
.不应该扔();
}
那么,我如何断言受保护的抽象方法实际上是在
DoSomethingCool
方法中调用的呢


如果它是来自注入依赖项的对象,我可以使用
Moq
设置一个mock,并断言调用了该方法,但由于该方法是测试对象内部的一个抽象方法,我如何断言调用了该方法?

关于这一点,可以说:

  • 看起来您可能测试太多,或者对其他实现的控制太多

    • (控制太多)通常,如果您想强制从
      抽象类中的另一个方法调用某个方法
      ,您不会将其设置为
      公共虚拟
      。通过这样做,您为未来的实现提供了更改此行为的能力。事实上,如果您删除了
      虚拟
      ,那么您就可以得到您想要的测试(见下文)。我确实提供了一种使
      保持虚拟的方法,但还是不推荐。这是不推荐的,因为你的SUT是你的模拟…这感觉不对
    • (测试太多)您应该只关注基本行为,而不是实现细节,以免您的测试变得太脆弱。我假设不仅仅是调用
      OnDoingSomethingCool
      方法,否则您应该将其作为主要方法。如果主要行为是这个调用(并且不仅仅是这个调用),那么我会在下面的
      NotRecommended
      方法中介绍它
  • 您不应该直接测试抽象类。您可能应该在中使用Roy Osherove所称的抽象测试类模式。这使得所有实现都可以测试您的行为。然后可以传入依赖项。如果您想要这个示例,或者甚至是抽象测试类模式下的简化示例,请告诉我

  • /

    使用最低保护量;
    ...
    不建议使用公共无效\u可能存在过多\u
    {
    //如果必须使DoSomethingTool保持虚拟
    //var baseMock=newmock{CallBase=true};
    var baseMock=new Mock();
    baseMock.Protected().Setup(“OnDoingSomethingCool”);
    baseMock.Object.doSomethingTool();
    baseMock.Protected();
    }
    
    您正在使用AutoFixture作为一个解决方案,但这实际上是一个有关最小起订量的问题。
    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());
    }