¿Por qué recibo una Excepción con el mensaje “Configuración no válida en un miembro no virtual (anulable en VB) …”?

Tengo una prueba de unidad donde tengo que burlarme de un método no virtual que devuelve un tipo 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); } } 

Así que tengo un objeto simulado de la clase XmlCupboardAccess y estoy intentando configurar el simulacro para este método en mi caso de prueba como se muestra a continuación

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

Pero esta línea arroja una excepción

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

¿Alguna sugerencia de cómo evitar esta excepción?

Moq no puede burlarse de los métodos no virtuales y las clases selladas. Al ejecutar una prueba con el objeto simulado, MOQ realmente crea un tipo de proxy en memoria que hereda de su “XmlCupboardAccess” y anula los comportamientos que ha configurado en el método “SetUp”. Y como sabe en C #, puede anular algo solo si está marcado como virtual, que no es el caso con Java. Java supone que todos los métodos no estáticos son virtuales por defecto.

Otra cosa que creo que deberías considerar es introducir una interfaz para tu “Acceso al armario” y comenzar a burlar la interfaz. Lo ayudaría a desacoplar su código y obtener beneficios a largo plazo.

Por último, existen frameworks como: TypeMock y JustMock que trabajan directamente con el IL y, por lo tanto, pueden simular métodos no virtuales. Sin embargo, ambos son productos comerciales.

Por favor, mira ¿ Por qué la propiedad que quiero burlar necesita ser virtual?

Puede que tenga que escribir una interfaz contenedora o marcar la propiedad como virtual / abstracta a medida que Moq crea una clase proxy que utiliza para interceptar llamadas y devolver los valores personalizados que .Returns(x) en la .Returns(x) .

Como ayuda para alguien que tuvo el mismo problema que yo, accidentalmente escribí mal el tipo de implementación en lugar de la interfaz, por ejemplo

 var mockFileBrowser = new Mock(); 

en lugar de

 var mockFileBrowser = new Mock(); 

Obtendrá este error también si está verificando que se llama a un método de extensión de una interfaz.

Por ejemplo, si te estás burlando:

 var mockValidator = new Mock>(); mockValidator .Verify(validator => validator.ValidateAndThrow(foo, null)); 

Obtendrá la misma excepción porque .ValidateAndThrow() es una extensión en la IValidator .

public static void ValidateAndThrow(this IValidator validator, T instance, string ruleSet = null)...

Código:

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

pero mira la excepción.