过去当我想模拟一个抽象类时,我只是在扩展抽象类的代码中创建一个模拟类,然后在我的单元测试中使用该类...
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来测试抽象类的默认返回值。这里有什么建议吗?
答案 0 :(得分:24)
如果将CallBase
设置为true,它将调用基类实现。
var mock = new Mock<MyConverter> { CallBase = true };
请参阅快速入门的 Customizing Mock Behavior Customizing Mock Behaviour部分。
如果没有期望覆盖成员(在Rhino Mocks中的a.k.a.“Partial Mocks”),则调用基类实现:default为false。
答案 1 :(得分:5)
您可以像在接口上一样在抽象类上设置模拟。为了测试抽象实现,您需要设置模拟对象以调用未定义的任何函数的基本方法:
var mock = new Mock<MyConverter>();
mock.CallBase = true;
Assert.AreEqual(expected value,mock.Object.ConvertBack(...));
答案 2 :(得分:2)
您是否阅读过Moq的任何入门指南?这很简单:
var mock = new Mock<MyConverter>();
var expected = ...;
mock.Setup(m => m.ConvertBack(...)).Returns(expected);
var actual = m.Object.ConvertBack(...);
Assert.AreEqual(expected, actual);
但是,当然,这是一个很糟糕的例子,因为你实际上并没有允许它测试任何真正的类。模拟对于为要进行单元测试的真实类提供模拟非常有用,并且您希望将其称为模拟的方法。
再次阅读你的问题后(Anthony Pegram更新了标题),我想知道你是否试图通过模拟ConvertBack
的实现来测试Convert
的真实实现。如果是这种情况,我有几点意见:
ConvertBack
可能不应该被声明virtual
,至少为了这个例子,Convert
和ConvertBack
成为不同服务的一部分:我感觉到可能因缺乏关注点而产生的代码异味。如果您确定需要这样做,它应该仍然相对简单:
var mock = new Mock<MyConverter>() {CallBase = true}; // hat tip: adrift
mock.Setup(m => m.Convert(...)).Returns(...);
var expected = ...;
var actual = m.Object.ConvertBack(...);
Assert.AreEqual(expected, actual);