Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/unit-testing/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 验证使用Moq调用受保护的抽象方法_C#_Unit Testing_Testing_Moq - Fatal编程技术网

C# 验证使用Moq调用受保护的抽象方法

C# 验证使用Moq调用受保护的抽象方法,c#,unit-testing,testing,moq,C#,Unit Testing,Testing,Moq,假设我有以下课程: public class TestBase { public bool runMethod1 { get; set; } public void BaseMethod() { if (runMethod1) ChildMethod1(); else ChildMethod2(); } protected abstract void ChildMethod1(); protected abstract vo

假设我有以下课程:

public class TestBase
{
  public bool runMethod1 { get; set; }

  public void BaseMethod() 
  {
    if (runMethod1)
      ChildMethod1();
    else 
      ChildMethod2();
  }

  protected abstract void ChildMethod1();
  protected abstract void ChildMethod2();
}
我也有课

public class ChildTest : TestBase
{
  protected override void ChildMethod1()
  {
    //do something
  } 

  protected override void ChildMethod2()
  {
    //do something completely different
  }

}
我使用的是Moq,我想编写一个测试,在调用BaseMethod()时验证是否调用了ChildMethod1(),并且runMethod1是否为true。是否可以使用Moq创建TestBase的实现,调用BaseMethod(),并验证是否在Moq实现上调用了ChildMethod

[Test]
public BaseMethod_should_call_correct_child_method()
{
  TestBase testBase;

  //todo: get a mock of TestBase into testBase variable

  testBase.runMethod1 = true;

  testBase.BaseMethod();

  //todo: verify that ChildMethod1() was called

}

看起来你是在测试行为,而不是公共界面。如果这是有意的,那么您可能可以查看关于测试私有成员的建议

是否可以使用Moq创建TestBase的实现,调用BaseMethod()并验证是否在Moq实现上调用了ChildMethod

这有点可能。但是接下来您将测试模拟对象,而不是真实对象

有两个问题可能会引导你走向正确的方向:

  • Degeneratn类是否返回与基类不同的值?如果是这样的话,您可以进行测试并忽略实现细节(这也使得重构更容易)

  • 子类调用不同的方法还是不同的依赖项?如果是这样,您可以检查依赖项


  • 这是一个小技巧,但是创建一个TestBase的子类,使ChildMethod1和ChildMethod成为公共的,然后Moqing呢?

    我知道怎么做了。您可以使用Moq模拟受保护的方法,通过进行严格的模拟,您可以验证它们是否被调用。现在我可以测试基类,而无需创建任何子类

    [Test]
    public BaseMethod_should_call_correct_child_method()
    {
      //strict mocks will make sure all expectations are met
      var testBaseMock = new Mock<TestBase>(MockBehavior.Strict);
    
      //expect that ChildMethod1() will be called once. (it's protected)
      testBaseMock.Protected().Expect("ChildMethod1")
        .AtMostOnce();
    
      var testBase = testBaseMock.Object;
    
      testBase.runMethod1 = true;
      testBase.BaseMethod();
    
      //make sure the method was called
      testBase.VerifyAll();
    }
    
    [测试]
    public BaseMethod\u应该调用\u correct\u child\u method()
    {
    //严格的模拟将确保满足所有期望
    var testBaseMock=newmock(MockBehavior.Strict);
    //预计ChildMethod1()将被调用一次。(它受保护)
    testBaseMock.Protected().Expect(“ChildMethod1”)
    .AtMostOnce();
    var testBase=testBaseMock.Object;
    testBase.runMethod1=true;
    testBase.BaseMethod();
    //确保调用了该方法
    testBase.VerifyAll();
    }
    
    您还可以将期望/设置设置为可验证,并且不需要严格的模拟:

      //expect that ChildMethod1() will be called once. (it's protected)
      testBaseMock.Protected().Expect("ChildMethod1")
        .AtMostOnce()
        .Verifiable();
    
      ...
    
      //make sure the method was called
      testBase.Verify();
    
    编辑
    此语法在当前版本的Moq中不起作用。请参阅,了解如何至少从4.0.10827开始执行此操作。此示例使您看起来像是在测试CLR,而不是您自己的代码。这就是你真正想要的吗?实际的代码更复杂。我根据对象的状态在子类中调用不同的方法。我只是想在这里写一个简单的例子,但我会更新它,以便有更多的东西要测试。