模拟抽象保护方法

时间:2014-11-27 15:19:13

标签: c# unit-testing moq

我有一个抽象类:

public abstract class MyClass
{
    protected abstract bool IsSavable();

    protected bool IsExecutable()
    {
        //New mode or edit mode
        if (ViewMode == ViewMode.New || ViewMode == ViewMode.Edit)
        {
            return IsSavable();
        }

        //Search mode
        if (ViewMode == ViewMode.Search)
        {
            return true;
        }

        return false;
    }
}

我想对这门课进行单元测试。因此,我需要嘲笑" IsSavable"方法。它应该总是返回" true"。

我知道如何用Moq模拟我的抽象类。但是,如何模拟我的抽象受保护方法,使其返回true?

函数IsSavable在我的抽象类中通过具体方法(IsExecuteable)调用。我想测试一下这个方法。我知道你们中的大多数人都会建议在班级里测试两个" IsSavable"实施。不幸的是,这将是很多类,我想只测试我的方法IsExecutable一次。

3 个答案:

答案 0 :(得分:9)

  

我想对这门课进行单元测试。因此,我需要模拟“IsSavable”方法。它应该总是返回“true”。

不,那是不合理的。您可以创建一个符合您需要的子类:

// Within your test code
class MyClassForTest : MyClass
{
    // TODO: Consider making this a property 
    protected override bool IsSavable()
    {
        return true;
    }
}

然后,当您想要运行测试时,请创建MyClassForTest而不是MyClass的实例。

我个人更喜欢使用依赖的模拟框架而不是我正在测试的类。

答案 1 :(得分:3)

只是为了证实@Jon所说的 - 你试图模拟受保护的方法并在抽象类上调用另一个受保护的方法这一事实表明了一种气味。

但是,通过引出重炮 - Moq's Protected()扩展,再次使用直接反射来实​​际调用SUT IsExecutable,实际上可以做你想做的事情:

// Arrange
var mockMyClass = new Mock<MyClass>();
mockMyClass.Object.ViewMode = ViewMode.New; // I've made an assumption or two here ...
mockMyClass.Protected().Setup<bool>("IsSavable").Returns(true);

// Act!
var result = (bool)mockMyClass.Object.GetType().InvokeMember("IsExecutable",
    BindingFlags.InvokeMethod | BindingFlags.NonPublic | BindingFlags.Instance,
    null,
    mockMyClass.Object,
    null);

// Assert
Assert.IsTrue(result);
mockMyClass.Protected().Verify<bool>("IsSavable", Times.Once());

但我个人倾向于重新考虑设计和方法耦合。

答案 2 :(得分:1)

从“MyClass”继承并覆盖IsSavable最快的事情。

在测试中可能有点难以区分正在测试的内容,但它可以解决问题。

此外,您可以考虑设计 - 也许应该有两个类 - &gt;一个用于可保存行为,一个用于unSavable?