我目前正在运行如下所示的测试:
// In Blah.cs
public class ClassUnderTest
{
public bool MethodUnderTest()
{
// Do a bunch of stuff...
return HelperMethod();
}
protected virtual bool HelperMethod()
{
bool success = false;
// Proprietary Hardware Access.
// Database Calls.
// File System Modifications.
return success;
}
}
// In TestBlah.cs
public class TestStub : ClassUnderTest
{
public bool HelperMethodReturnValue;
protected override bool HelperMethod()
{
return HelperMethodReturnValue;
}
}
[TestClass]
public class TestingClass
{
[TestMethod]
public void ClassUnderTest_MethodUnderTest_TestHelperReturnsTrue()
{
var stub = new TestStub();
stub.HelperMethodReturnValue = true;
Assert.IsTrue(stub.MethodUnderTest());
}
[TestMethod]
public void ClassUnderTest_MethodUnderTest_TestHelperReturnsFalse()
{
var stub = new TestStub();
stub.HelperMethodReturnValue = false;
Assert.IsFalse(stub.MethodUnderTest());
}
}
以上内容对于简单的事情看起来很好,但是存根类会快速地呈指数级增长和更复杂。 我想用Moq替换存根类。但是这不会编译,因为由于某种原因我无法在受保护的方法上设置返回值。
[TestMethod]
public void ClassUnderTest_MethodUnderTest_TestHelperReturnsFalse()
{
var mockClass = new Mock<ClassUnderTest>();
mockClass.Protected().Setup("HelperMethod").Returns(false);
Assert.IsFalse(mockClass.Object.MethodUnderTest());
}
任何人都知道我该怎么做?我可以用moq做这个吗?
答案 0 :(得分:25)
查看moq source code我猜测,您需要显式调用安装程序的通用版本。非泛型版似乎用于void方法。所以试试
mockClass.Protected().Setup<bool>("HelperMethod").Returns(false);
除此之外,我建议重新思考你的课堂设计。如果HelperMethod()正在做这么多事情,那么将自己的类作为依赖注入ClassUnderTest是值得的。测试模拟对象,而不是使用模拟对象来测试“真实”的东西,而不是模拟框架的制作(至少在第一时间)。
答案 1 :(得分:4)
受保护的方法不是隔离依赖项的好方法,但有时会出现这种情况,特别是在调整遗留代码以实现可测试性时。避免基于字符串的笨拙Moq语法的一个选项是使方法“受保护内部”(或者如果您不打算在正常情况下从其他程序集中覆盖它,则只是“内部”。)然后在程序集上使用InternalsVisibleTo揭露方法。这有点像黑客攻击,但为此目的使用受保护的方法已经是一个黑客攻击了。在某些方面,我更喜欢“内部”方法,因为它清楚地表明这是一个你不应该使用的后门方法(测试除外),而不是你可能希望在正常情况下覆盖的受保护方法的使用。