Estoy trabajando en .NET 4.0 usando C # en Windows 7.
Quiero probar la comunicación entre algunos métodos usando mock. El único problema es que quiero hacerlo sin implementar una interfaz. ¿Es eso posible?
Acabo de leer muchos temas y algunos tutoriales sobre objetos simulados, pero todos se utilizan para simular interfaces, no las clases. Intenté utilizar los marcos Rhino y Moq.
Respuestas:
Simplemente marque cualquier método que necesite falsificar como
virtual
(y no privado). Entonces podrás crear una falsificación que pueda anular el método.Si usa
new Mock<Type>
y no tiene un constructor sin parámetros, puede pasar los parámetros como los argumentos de la llamada anterior, ya que toma un tipo deparam Objects
fuente
La mayoría de los marcos de simulación (incluidos Moq y RhinoMocks) generan clases de proxy como sustituto de su clase simulada y anulan los métodos virtuales con el comportamiento que usted define. Debido a esto, solo puede simular interfaces o métodos virtuales en clases concretas o abstractas. Además, si se está burlando de una clase concreta, casi siempre debe proporcionar un constructor sin parámetros para que el marco burlón sepa cómo crear una instancia de la clase.
¿Por qué la aversión a crear interfaces en su código?
fuente
Con MoQ, puede simular clases concretas:
var mocked = new Mock<MyConcreteClass>();
pero esto le permite anular el
virtual
código (métodos y propiedades).fuente
new Mock<MyConcreteClass>(param1, anotherParam, thirdParam, evenMoreParams);
Creo que es mejor crear una interfaz para esa clase. Y cree una prueba unitaria usando la interfaz.
Si no tiene acceso a esa clase, puede crear un adaptador para esa clase.
Por ejemplo:
public class RealClass { int DoSomething(string input) { // real implementation here } } public interface IRealClassAdapter { int DoSomething(string input); } public class RealClassAdapter : IRealClassAdapter { readonly RealClass _realClass; public RealClassAdapter() => _realClass = new RealClass(); int DoSomething(string input) => _realClass.DoSomething(input); }
De esta manera, puede crear fácilmente un simulacro para su clase usando IRealClassAdapter.
Espero que funcione.
fuente
Los marcos de simulación estándar están creando clases de proxy. Esta es la razón por la que técnicamente se limitan a interfaces y métodos virtuales.
Si también desea simular métodos 'normales', necesita una herramienta que funcione con instrumentación en lugar de generación de proxy. Por ejemplo, MS Moles y Typemock pueden hacer eso. Pero el primero tiene una 'API' horrible, y el segundo es comercial.
fuente
Si no puede cambiar la clase bajo prueba, entonces la única opción que puedo sugerir es usar MS Fakes https://msdn.microsoft.com/en-us/library/hh549175.aspx . Sin embargo, MS Fakes solo funciona en algunas ediciones de Visual Studio.
fuente
Si lo peor empeora, puede crear una interfaz y un par de adaptadores. Cambiaría todos los usos de ConcreteClass para usar la interfaz en su lugar, y siempre pasaría el adaptador en lugar de la clase concreta en el código de producción.
El adaptador implementa la interfaz, por lo que el simulacro también puede implementar la interfaz.
Es más un andamiaje que simplemente hacer un método virtual o simplemente agregar una interfaz, pero si no tiene acceso a la fuente de la clase concreta, puede salir de un aprieto.
fuente
Me enfrenté a algo así en uno de los proyectos antiguos y heredados en los que trabajé que no contiene interfaces o mejores prácticas y también es demasiado difícil hacerlos cumplir, construir cosas nuevamente o refactorizar el código debido a la madurez del negocio del proyecto, así que en mi proyecto UnitTest, solía crear un Wrapper sobre las clases que quiero simular y esa interfaz de implementación de envoltorio que contiene todos mis métodos necesarios con los que quiero configurar y trabajar.Ahora puedo simular el envoltorio en lugar de la clase real.
Por ejemplo:
Servicio que desea probar que no contiene métodos virtuales o interfaz de implementación
public class ServiceA{ public void A(){} public String B(){} }
Envoltorio a moq
public class ServiceAWrapper : IServiceAWrapper{ public void A(){} public String B(){} }
La interfaz Wrapper
public interface IServiceAWrapper{ void A(); String B(); }
En la prueba unitaria, ahora puede simular la envoltura:
public void A_Run_ChangeStateOfX() { var moq = new Mock<IServiceAWrapper>(); moq.Setup(...); }
Puede que esta no sea la mejor práctica, pero si las reglas de su proyecto lo obligan a hacerlo, hágalo. También coloque todos sus Wrappers dentro de su proyecto de prueba unitaria o proyecto Helper especificado solo para las pruebas unitarias para no sobrecargar el proyecto con envoltorios o adaptadores innecesarios.
Actualización: esta respuesta de más de un año, pero en este año enfrenté muchos escenarios similares con diferentes soluciones. Por ejemplo, es muy fácil usar Microsoft Fake Framework para crear simulacros, falsificaciones y stubs e incluso probar métodos privados y protegidos sin interfaces. Puede leer: https://docs.microsoft.com/en-us/visualstudio/test/isolates-code-under-test-with-microsoft-fakes?view=vs-2017
fuente