【发布时间】:2011-02-18 20:37:18
【问题描述】:
我非常感谢 Moq 的 Loose 模拟行为,它在未设置期望时返回默认值。它既方便又节省了我的代码,而且还起到了安全措施的作用:在单元测试期间不会无意中调用依赖项(只要它们是虚拟的)。
但是,当被测方法恰好是虚拟方法时,我对如何保持这些好处感到困惑。
在这种情况下,我确实想调用那个方法的真实代码,同时仍然松散地模拟类的其余部分。
我在搜索中发现的只是我可以设置mock.CallBase = true 以确保调用该方法。但是,这会影响整个班级。我不想这样做,因为它让我对隐藏调用依赖关系的类中的所有其他属性和方法进退两难:如果 CallBase 为真,那么我必须要么
- 为隐藏依赖关系的所有属性和方法设置存根 -- 即使我的测试认为它不需要关心这些依赖关系,或者
- 希望我不要忘记设置任何存根(并且以后不会将新的依赖项添加到代码中)- 单元测试遇到真正的依赖项的风险。
我想我想要的是:mock.Setup(m => m.VirtualMethod()).CallBase();
这样当我调用mock.Object.VirtualMethod() 时,Moq 就会调用真正的实现...
问:使用 Moq,当我模拟类以存根几个依赖项时,有什么方法可以测试虚拟方法? IE。无需诉诸 CallBase=true 并且不必存根所有依赖项?
示例代码说明
(使用 MSTest、InternalsVisibleTo DynamicProxyGenAssembly2)
在以下示例中,TestNonVirtualMethod 通过,但 TestVirtualMethod 失败 - 返回 null。
public class Foo
{
public string NonVirtualMethod() { return GetDependencyA(); }
public virtual string VirtualMethod() { return GetDependencyA();}
internal virtual string GetDependencyA() { return "! Hit REAL Dependency A !"; }
// [... Possibly many other dependencies ...]
internal virtual string GetDependencyN() { return "! Hit REAL Dependency N !"; }
}
[TestClass]
public class UnitTest1
{
[TestMethod]
public void TestNonVirtualMethod()
{
var mockFoo = new Mock<Foo>();
mockFoo.Setup(m => m.GetDependencyA()).Returns(expectedResultString);
string result = mockFoo.Object.NonVirtualMethod();
Assert.AreEqual(expectedResultString, result);
}
[TestMethod]
public void TestVirtualMethod() // Fails
{
var mockFoo = new Mock<Foo>();
mockFoo.Setup(m => m.GetDependencyA()).Returns(expectedResultString);
// (I don't want to setup GetDependencyB ... GetDependencyN here)
string result = mockFoo.Object.VirtualMethod();
Assert.AreEqual(expectedResultString, result);
}
string expectedResultString = "Hit mock dependency A - OK";
}
【问题讨论】:
-
只是简要说明您/我的需求:在模拟时需要
CallBase版本,而不是 “如果没有期望覆盖成员,则调用基类实现”,即所谓的Partial Mocks,请调用mocked members的基础实现!我想将新函数命名为CallBaseOnMockedMemberOnly:D
标签: unit-testing moq