Pregunta

Hace un mes terminé de leer el libro "El arte de las pruebas unitarias" y hoy finalmente tuve tiempo de comenzar a usar Rhino Mocks con pruebas unitarias, un servicio que envía/recibe mensajes a dispositivos (UDP) y guarda/carga datos de la base de datos.
Por supuesto, quiero aislar la base de datos y la comunicación UDP.

Por ejemplo, para el acceso a la base de datos, tenemos algunas clases con métodos estáticos, llamémoslas:

  • ÁreaADBAcceso
  • ÁreaBDBAcceso
  • ÁreaCDBAcceso

Estas clases tenían métodos estáticos que ejecutaban el acceso a la base de datos.
Para poder eliminarlos, hice públicos virtuales sus métodos.

Luego comencé a refactorizar el código para poder reemplazar la instancia de estas clases en el código.
Después de probar diferentes cosas, terminé con una clase de fábrica que parece hacer las cosas muy fáciles.

public class ObjectFactory
{
    private static Dictionary<Type, object> Instances = new Dictionary<Type, object>();

    public static T GetInstance<T>() where T : new()
    {
        if(Instances.ContainsKey(typeof(T)))
            return (T)Instances[typeof(T)];

        return new T();
    }

    public static void SetInstance<T>(object obj)
    {
        Instances[typeof(T)] = obj;
    }
}

Luego en el código, puedo usar

private AreaADBAccess DBAccess = ObjectFactory.GetInstance<AreaADBAccess>();

Y en el método de prueba hago algo como

AreaADBAccess dbAccess = mocks.Stub<AreaADBAccess>();
using (mocks.Record())
{
...
}
ObjectFactory.SetInstance<AreaADBAccess>(dbAccess);
//Invoke the test method
...

Esta es una primera solución y me doy cuenta de que se puede hacer de mejor manera.
¿Puedes comentarlo ahora y señalarme las mejores prácticas?
¿Puedes explicarme también por qué querría tener una interfaz en lugar de definir los métodos como virtuales?Parece inútil repetir los encabezados del método en 2 lugares.
¡Gracias!

¿Fue útil?

Solución

Probablemente podrías utilizar contenedores de IoC como Windsor, StructureMap o Ninject, que te harían la vida mucho más fácil y, de hecho, también funcionan como "fábrica" ​​que has creado manualmente, pero son mucho más potentes.

También hay contenedores de simulación automática que crearán automáticamente dependencias simuladas para sus clases para que pueda guardar líneas de código adicionales y hacer que su prueba sea menos frágil.

En cuanto a la pregunta sobre la necesidad de una interfaz en lugar de clases, se trata básicamente del principio de inversión de dependencia, que establece que los módulos (clases) de nivel superior no deben depender de los módulos (clases) de nivel inferior, ambos deben depender de abstracciones.Las interfaces son esas abstracciones.Te sugiero que eches un vistazo a los principios S.O.L.I.D que te harán la vida mucho más fácil, al menos a mí me lo hicieron.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top