c# - 为什么我会收到消息 "Invalid setup on a non-virtual (overridable in VB) member..."的异常?

标签 c# unit-testing moq

我有一个单元测试,我必须模拟一个返回 bool 类型的非虚拟方法

public class XmlCupboardAccess
{
    public bool IsDataEntityInXmlCupboard(string dataId,
                                          out string nameInCupboard,
                                          out string refTypeInCupboard,
                                          string nameTemplate = null)
    {
        return IsDataEntityInXmlCupboard(_theDb, dataId, out nameInCupboard, out refTypeInCupboard, nameTemplate);
    }
}

所以我有一个 XmlCupboardAccess 类的模拟对象,我正尝试在我的测试用例中为此方法设置模拟,如下所示

[TestMethod]
Public void Test()
{
    private string temp1;
    private string temp2;
    private Mock<XmlCupboardAccess> _xmlCupboardAccess = new Mock<XmlCupboardAccess>();
    _xmlCupboardAccess.Setup(x => x.IsDataEntityInXmlCupboard(It.IsAny<string>(), out temp1, out temp2, It.IsAny<string>())).Returns(false); 
    //exception is thrown by this line of code
}

但是这一行抛出异常

Invalid setup on a non-virtual (overridable in VB) member: 
x => x.IsDataEntityInXmlCupboard(It.IsAny<String>(), .temp1, .temp2, 
It.IsAny<String>())

有什么建议可以解决这个异常吗?

最佳答案

Moq 不能模拟非虚拟方法和密封类。在使用模拟对象运行测试时,MOQ 实际上创建了一个内存中代理类型,它继承自您的“XmlCupboardAccess”并覆盖您在“SetUp”方法中设置的行为。正如您在 C# 中所了解的那样,只有当某些东西被标记为虚拟时,您才能覆盖它,而 Java 则不是这种情况。默认情况下,Java 假定每个非静态方法都是虚拟的。

我认为您应该考虑的另一件事是为“CupboardAccess”引入一个接口(interface),然后开始模拟该接口(interface)。这将帮助您解耦代码并从长远来看受益。

最后,还有像这样的框架:TypeMockJustMock它直接与 IL 一起工作,因此可以模拟非虚拟方法。然而,两者都是商业产品。

关于c# - 为什么我会收到消息 "Invalid setup on a non-virtual (overridable in VB) member..."的异常?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21768767/

相关文章:

c# - Moq 是在模拟子接口(interface)返回值并忽略中间步骤是错误还是功能?

c# - 最小起订量和代码契约(Contract)

c# - Moq 框架 Func<T,T>

c# - 在 WPF 中,PreviewTextInput 是否总是只给出一个字符?

c# - 当我们覆盖 OnPaint 时,我们什么时候应该调用 base.OnPaint()?

c++依赖注入(inject)来测试类系统调用的类

c++ - 在gtest中调用另一个TEST_F中的一个TEST_F

C# 方法返回 var

c# - List<SelectListItem> 如何在 View 中安全地转换为 SelectList

java - 验证私有(private)方法未执行 JMockit