c# - que - no se puede crear una instancia de una interfaz
¿Cómo me burlo de una clase sin una interfaz? (8)
Estoy trabajando en .NET 4.0 usando C # en Windows 7.
Quiero probar la comunicación entre algunos métodos usando simulacro. 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 ellos se usaban para simular interfaces, y no las clases. Intenté usar frameworks de Rhino y Moq.
Con MoQ, puede simular clases concretas:
var mocked = new Mock<MyConcreteClass>();
pero esto le permite anular virtual
código virtual
(métodos y propiedades).
Creo que es mejor crear una interfaz para esa clase. Y crea una prueba de unidad 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{
private readonly RealClass _realClass;
public RealClassAdapter(){
_realClass = new RealClass();
}
int DoSomething(string input){
_realClass.DoSomething(input);
}
}
De esta forma, puedes crear simulacros fácilmente para tu clase usando IRealClassAdapter.
Espero que funcione.
La mayoría de los frameworks burlones (Moq y RhinoMocks incluidos) generan clases proxy como sustituto de su clase simulada, y anulan los métodos virtuales con el comportamiento que defina. Debido a esto, solo puede simular interfaces o métodos virtuales en clases concretas o abstractas. Además, si te estás burlando de una clase concreta, casi siempre necesitas proporcionar un constructor sin parámetros para que el framework de burlas sepa cómo crear instancias de la clase.
¿Por qué la aversión a crear interfaces en tu código?
Los marcos de burla estándar están creando clases de proxy. Esta es la razón por la cual están técnicamente limitados a interfaces y métodos virtuales.
Si también quieres burlar los métodos "normales", necesitas 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 un horrible ''API'', y el último es comercial.
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 muy difícil hacerlos volver a construirlos o refactorizar el código debido a la madurez del negocio del proyecto. en mi proyecto UnitTest solía crear un Wrapper sobre las clases que quiero simular y esa interfaz implementadora de contenedor que contiene todos mis métodos necesarios con los que quiero configurar y trabajar. Ahora puedo simular el contenedor en lugar de la clase real.
Por ejemplo:
Servicio que desea probar que no contiene métodos virtuales o implementar interfaz
public class ServiceA{
public void A(){}
public String B(){}
}
Contenedor 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 puedes simularte con el envoltorio:
public void A_Run_ChangeStateOfX()
{
var moq = new Mock<IServiceAWrapper>();
moq.Setup(...);
}
Esta podría no ser la mejor práctica, pero si las reglas de su proyecto lo fuerzan de esta manera, hágalo. Coloque también todas sus envolturas dentro de su proyecto de Prueba de Unidad o proyecto Helper especificado solo para las pruebas de unidad para no sobrecargar el proyecto con envoltorios o adaptadores innecesarios
Si empeora, puede crear una interfaz y un par de adaptadores. En su lugar, cambiaría todos los usos de ConcreteClass para usar la interfaz, 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 tienes acceso a la fuente para la clase concreta, puede sacarte de un aprieto.
Si no puede cambiar la clase bajo prueba, 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.
Simplemente marque cualquier método que necesite para simular como virtual
(y no privado). Entonces podrás crear un falso que pueda anular el método.
Si usa un 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 de param Objects