如何使用mole测试虚拟方法

本文关键字:虚拟 方法 测试 mole 何使用 | 更新日期: 2023-09-27 18:15:57

如何使用mole测试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方法的默认实现呢?

如何使用mole测试虚拟方法

这里我就不提存根了。存根/模拟用于想要模拟依赖项的行为。你会存根你的someeclass,如果有你想测试的someeclassclient,它使用someeclass:

    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中,那么您也必须将它们添加到这个虚拟继承程序中,从而增加了测试维护开销。

我的纯粹主义者认为,应该不去管受保护的成员,只通过公共接口测试它们。但是,在你的情况下,这可能是可行的,也可能不是,我真的没有看到这种方法有什么害处。

stub和mole用于将一个类从它拥有的任何依赖中隔离出来,无论是环境依赖还是类依赖。这个类没有任何依赖关系,所以为什么要尝试将其移除或存根呢?

如果您想要确保这个基类在人们重写它时能够正常工作,那么您将需要创建一个测试实现。在这种情况下,您的测试用例或多或少应该是这样的:

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特性,而不是像mole那样的大型付费依赖。反射和动态允许您访问受保护或私有成员。请看下面的例子:

  • http://igoro.com/archive/use-c-dynamic-typing-to-conveniently-access-internals-of-an-object/