Why am I getting an Exception with the message “Invalid setup on a non-virtual (overridable in VB) member…”?

匿名 (未验证) 提交于 2019-12-03 02:45:02

问题:

I have a unit test where I have to mock a non-virtual method that returns a bool type

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);     } } 

So I have a mock object of XmlCupboardAccess class and I am trying to setup mock for this method in my test case as shown below

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

But this line throws exception

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

Any suggestion how to get around this exception?

回答1:

Moq cannot mock non-virtual methods and sealed classes. While running a test using mock object, MOQ actually creates an in-memory proxy type which inherits from your "XmlCupboardAccess" and overrides the behaviors that you have set up in the "SetUp" method. And as you know in C#, you can override something only if it is marked as virtual which isn't the case with Java. Java assumes every non-static method to be virtual by default.

Another thing I believe you should consider is introducing an interface for your "CupboardAccess" and start mocking the interface instead. It would help you decouple your code and have benefits in the longer run.

Lastly, there are frameworks like : TypeMock and JustMock which work directly with the IL and hence can mock non-virtual methods. Both however, are commercial products.



回答2:

Please see Why does the property I want to mock need to be virtual?

You may have to write a wrapper interface or mark the property as virtual/abstract as Moq creates a proxy class that it uses to intercept calls and return your custom values that you put in the .Returns(x) call.



回答3:

Code:

private static void RegisterServices(IKernel kernel) {     Mock mock=new Mock();     mock.Setup(x => x.Products).Returns(new List     {         new Product {Name = "Football", Price = 23},         new Product {Name = "Surf board", Price = 179},         new Product {Name = "Running shose", Price = 95}     });      kernel.Bind().ToConstant(mock.Object); }         

but see exception.



标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!