3

假设我有以下课程:

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() 并且 runMethod1 为 true 时正在调用 ChildMethod1()。是否可以使用 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

}
4

4 回答 4

5

您还可以将期望/设置设置为可验证,而无需严格模拟:

  //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 开始,请参阅此问题以了解如何执行此操作

于 2009-02-03T03:52:29.487 回答
4

我想出了如何做到这一点。您可以使用 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();
}
于 2008-12-24T18:48:00.883 回答
1

这有点 hack,但是创建一个 TestBase 的子类,将 ChildMethod1 和 ChildMethod 公开,然后 Moqing 怎么样?

于 2008-12-24T03:51:45.997 回答
0

似乎您在测试行为而不是公共接口。如果这是有意的,那么您可能会查看测试私人成员的建议。

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

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

两个问题可能会引导您朝着正确的方向前进:

  1. descendatn 类返回的值是否与基类不同?如果是这样,您可以对此进行测试并忽略实施细节(也使重构更容易)。

  2. 后代类是否调用不同的方法或不同的依赖项?如果是这样,您可以检查依赖项。

于 2008-12-24T02:47:34.707 回答