如何使用moq测试抽象类中的具体方法?

在过去,当我想模拟一个抽象类时,我只是在扩展抽象类的代码中创建一个模拟类,然后在我的unit testing中使用该类…

public abstract class MyConverter : IValueConverter { public abstract Object Convert(...) { ... }; public virtual Object ConvertBack(...) { ... } } private sealed class MockedConverter : MyConverter { ... } [TestMethod] public void TestMethod1() { var mock = new MockedConverter(); var expected = ...; var actual = mock.ConvertBack(...); Assert.AreEqual(expected, actual); } 

我想养成使用Moq的习惯。 我不确定如何使用Moq来测试抽象类的默认返回值。 有什么建议吗?

如果将CallBase设置为true,它将调用基类实现。

 var mock = new Mock { CallBase = true }; 

自定义模拟行为 自定义快速入门的模拟行为部分。

如果没有期望覆盖成员(在Rhino Mocks中称为“Partial Mocks”),则调用基类实现:default为false。

您可以像在接口上一样在抽象类上设置Mock。 为了测试抽象实现,您需要设置模拟对象以调用未定义的任何函数的基本方法:

 var mock = new Mock(); mock.CallBase = true; Assert.AreEqual(expected value,mock.Object.ConvertBack(...)); 

您是否阅读过Moq的任何入门指南? 这很简单:

 var mock = new Mock(); var expected = ...; mock.Setup(m => m.ConvertBack(...)).Returns(expected); var actual = m.Object.ConvertBack(...); Assert.AreEqual(expected, actual); 

但是,当然,这是一个很糟糕的例子,因为你实际上并没有允许它测试任何真正的类。 模拟对于为要进行unit testing的真实类提供模拟非常有用,并且您期望将其称为您已模拟的方法。

更新

在再次阅读你的问题后(​​Anthony Pegram更新了标题),我想知道你是否试图通过模拟Convert的实现来测试ConvertBack的真实实现。 如果是这种情况,我有几点意见:

  1. ConvertBack可能不应该被声明为virtual ,至少为了这个例子,
  2. 您可能希望重构代码,以便ConvertConvertBack成为不同服务的一部分:我感觉到可能由于缺乏关注点而产生的代码异味。

如果您确定需要这样做,它应该仍然相对简单:

 var mock = new Mock() {CallBase = true}; // hat tip: adrift mock.Setup(m => m.Convert(...)).Returns(...); var expected = ...; var actual = m.Object.ConvertBack(...); Assert.AreEqual(expected, actual);