在非虚拟(在VB中可重写)成员无效的设置

我有一个unit testing,我必须模拟一个非虚方法返回一个布尔types

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类的模拟对象,我想在我的testing用例中设置这个方法的模拟,如下所示

 [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 } 

但是这行会抛出exception

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

任何build议如何解决这个exception?

Moq不能模拟非虚拟方法和密封类。 在使用模拟对象运行testing时,MOQ实际上会创build一个从“XmlCupboardAccess”inheritance的内存代理types,并覆盖您在“SetUp”方法中设置的行为。 正如你在C#中所知道的,只有当它被标记为虚拟时才可以重写某些东西,而Java并不是这样。 Java假定每个非静态方法默认为虚拟的。

我相信你应该考虑的另一件事是为你的“CupboardAccess”引入一个界面,并开始嘲笑界面。 这将帮助你解耦你的代码,并在更长的时间内有好处。

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

请参阅为什么我想模拟的财产需要虚拟?

您可能必须编写一个包装接口或将该属性标记为虚拟/抽象,因为Moq会创build一个代理类来拦截调用并返回您在.Returns(x)调用中放置的自定义值。

码:

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

但看到exception。