如何使用Moles测试IsHappy
函数?
class SomeClass
{
protected virtual bool IsHappy(string mood)
{
return (mood == "Happy");
}
}
我尝试使用Stub来测试是否
SSomeClass stub = new SSomeClass();
stub.CallBase = true;
Assert.IsTrue(stub.IsHappyString("Happy"));
...但IsHappyString
方法返回null,因此抛出NullReference
异常。
那么,我该如何测试IsHappy
方法的默认实现?
答案 0 :(得分:2)
我在这里忘记了存根。 Stubs / mocks用于伪造依赖项的行为。如果您想要测试SomeClassClient并且使用了SomeClass,那么你可以存储你的SomeClass:
public class Foo
{
public virtual int GetFoosInt()
{
return 12;
}
}
public class FooClient
{
private Foo _foo;
public FooClient(Foo foo)
{
_foo = foo;
}
public int AddOneToFoosInt()
{
return _foo.GetFoosInt() + 1;
}
}
在这个例子中,当测试FooClient时,你要测试的是它返回的不仅仅是“GetFoosInt()”。您实际上并不关心FoosInt用于测试FooClient的内容。因此,您可以创建一个Foo存根,您可以在其中设置GetFoosInt以返回您想要的任何内容。
在您的情况下,测试受保护的虚拟成员,我会选择:
[TestClass]
public class SomeClassTest
{
private class DummySomeClass : SomeClass
{
public bool IsHappyWrapper(string mood)
{
return IsHappy(mood);
}
}
[TestMethod]
public void SomeTest()
{
var myClass = new DummySomeClass();
Assert.IsTrue(myClass.IsHappyWrapper("Happy"));
}
}
这使您可以“直接”访问受保护的虚拟测试默认行为。唯一需要注意的是,如果你开始定义抽象成员并一般地添加到SomeClass,你也必须将它们添加到这个虚拟继承者中,增加测试维护开销。
我的纯粹主义者说你应该让受保护的成员独自离开,只通过公共界面测试它们。但是,在你的情况下,这可能是也可能不实际,我认为这种方法没有任何损害。
答案 1 :(得分:1)
Stubs和Moles用于将类与其具有的任何依赖项隔离,无论是环境依赖还是类依赖。这个类没有任何依赖关系,那你为什么要试图mole或stub?
如果要在人们覆盖它时确保此基类正常工作,那么您需要创建一个测试实现。在这种情况下,这或多或少是您的测试用例的样子:
public SomeClassTestAdapter : SomeClass
{
public bool GetIsHappy(string mood)
{
return IsHappy(mood);
}
}
[Test]
public void ShouldReturnTrueWhenPassedHappy()
{
var classUnderTest = new SomeClassTestAdapter();
bool result = classUnderTest.IsHappy("Happy");
Assert.IsTrue(result, "Expected result to be true");
}
[Test]
public void ShouldReturnFalseWhenPassedLowerCaseHappy()
{
var classUnderTest = new SomeClassTestAdapter();
bool result = classUnderTest.IsHappy("happy");
Assert.IsFalse(result, "Expected result to be false");
}
[Test]
public void ShouldReturnFalseWhenPassedNull()
{
var classUnderTest = new SomeClassTestAdapter();
bool result = classUnderTest.IsHappy(null);
Assert.IsFalse(result, "Expected result to be false");
}
等
此代码中没有地方应该挤入存根或痣。
如果您不想为此案例创建适配器类,则可以使用内置的.Net功能,而不是像Moles这样的大型付费依赖项。通过思考和动态,您可以访问受保护或私有成员。见这个例子: