小编典典

为什么我会收到一条异常消息“非虚拟(在 VB 中可覆盖)成员上的设置无效...”?

all

我有一个单元测试,我必须模拟一个返回 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>())

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


阅读 59

收藏
2022-07-17

共1个答案

小编典典

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

我认为您应该考虑的另一件事是为您的“CupboardAccess”引入一个界面并开始模拟界面。它将帮助您解耦代码并从长远来看有好处。

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

2022-07-17