2011-11-08 16 views
7

He leído la mayoría de las preguntas relacionadas con SO (here, here y there). La última pregunta propone cuatro alternativas para crear un código que haga que los métodos estáticos sean comprobables por unidad. Quiero preguntar sobre mi caso particular: tenemos un proyecto de "capa de lógica de negocios" o "reglas" que contiene 45 clases estáticas (sin estado, solo métodos estáticos). Además, no son fácilmente comprobables por sí mismos: la mayoría accede a la base de datos y al sistema de archivos. No es tan malo, de todos modos: para acceder a la base de datos, usan la instancia única de alguna clase de Mapper (todos los Mappers son Singleton). Cada vez que intento probar la unidad de algo, me tropiezo con esta pared. El mayor problema es que este es un código muy, muy importante, y los cambios deben planearse con mucho cuidado. Mi pregunta: ¿cómo debo hacer para que esta unidad sea más comprobable? ¿Debo escribir 45 interfaces y usar la inyección de dependencia? Aun así, ¿cómo resisto/simulacro de los Mappers?Código de prueba de unidad que llama a métodos estáticos

PS: He estado leyendo Michael plumas 'Utilización del código de legado', por lo que las referencias directas son bienvenidos (otros libros también :)

Editar: Dado que algunas personas dijeron que las soluciones podrían ser dependiente de la plataforma , Estoy trabajando en .NET (C# y algunos VB.NET)

Respuesta

10

La situación actual es probable que nadie se atreva a cambiar nada en el código porque podría romperse en formas inesperadas. Asegúrese de que todo el mundo entiende que está mejorando la situación: los cambios podría romper el código, pero a diferencia de antes, esas roturas serán encontró y vez que se han encontrado, que serán fijados siempre.

Dicho esto, el siguiente paso depende de su experiencia y su crédito con el equipo. Si quieres ir a lo seguro, utilice un código como éste (la sintaxis de Java):

Mapper { 
    public static Mapper INSTANCE = new Mapper(); // NEW code 

    protected void doImpl() { // NEW CODE 
     ... code copied from impl()... // OLD code, NEW PLACE 
    } 

    public static void impl() { // OLD code 
     INSTANCE.doImpl(); // NEW code 
    } 

    // OLD code ... 
} 

Este es un cambio muy simple que le permite sobrescribir INSTANCE de sus pruebas. Para el código de producción, no hace nada y el valor predeterminado hará que el código se comporte exactamente como antes.

De esta manera, puede reemplazar un método a la vez. Puede dejar de seguir este camino en cualquier momento: cada cambio lleva solo un par de minutos y es una refactorización: el código hace exactamente lo mismo que antes. Como cada cambio es tan pequeño y no puede romper nada, puede reemplazar un método, escribir todas las pruebas de unidad que no pudo escribir antes, enjuagar, repetir. Por último, si no desea/necesita volver a trabajar todos los métodos estáticos, este enfoque le da todo el margen de maniobra que podría pedir.

En un segundo paso, puede presentar DI o cualquier otra tecnología que lo hará feliz. La ventaja de este enfoque: cuando llegue a los cambios complejos, ya tendrá pruebas unitarias que lo protegerán.

Si comenzó con DI, tendría que cambiar una gran cantidad de código en todo tipo de lugares, sin pruebas de unidad adecuadas que podrían protegerlo.

2

Su pregunta está realmente relacionada con la plataforma, en el mundo de Microsoft puede usar Microsoft Moles para probar métodos estáticos. Y simula métodos estáticos.

En el mundo java probablemente existan otras herramientas o debe evitar el uso de estáticas.

En otras plataformas hay otras herramientas, etc.

En general, cualquier método estático hará que su código sea menos comprobable. En mi opción, es mejor evitar statics y singletons (estado global) a cualquier costo. El código comprobable es la parte más importante de tu código si quieres cambiar algo más adelante. El código testable normalmente también es más legible.

Moles and Pex

3

hacer que la interfaz de la clase Mapper y reemplazar la funcionalidad asignador con una nueva aplicación moc. Creo que necesitarás implementar la fábrica abstracta que generará instancias de Mappers. Así que haga que una IMapperFactory y dos implementaciones de esta DBMapperFactory y MocMapperFactory pasen la instancia de este objeto a su código donde acceda a los Mappers y los genere con esta instancia.

Gl.

+1

Suena bien. Eso se encargaría de hacer los métodos estáticos comprobables, pero ¿qué hay del código que los llama? En otra nota, solo curiosidad ... ¿Es "GI" algún tipo de firma, o es un acrónimo? (Soy de Argentina) –

+0

Gl == Buena Suerte :). Para el código que usa Mapper, debe adaptarlo para usar la interfaz de fábrica en lugar de getInstance por singleton. – AlexTheo

1

La clase estática se puede burlar, aunque sin saber qué idioma/entorno está utilizando, no hay forma de decir cómo.

Tuve una base de código que terminó exactamente como lo que dijiste; creamos interfaces e implementaciones predeterminadas de unas pocas docenas de clases estáticas (no entre en pánico - generación de código). Las impls predeterminadas simplemente delegan a los singletons.

Las clases de llamada se cambiaron a DI utilizando las impls predeterminadas, pero fueron mucho más fáciles de probar. Las clases estáticas con dependencias en otras clases estáticas o singletons se movieron a usar las impls predeterminadas.

Se burla de un singleton como cualquier otra clase; si tiene un getInstance (o equivalente), puede hacer que devuelva lo que desee. O puede seguir la misma ruta y usar DI.

+0

Bien, estoy usando .NET (pregunta actualizada). ¿Es posible burlarse de una clase estática fácilmente allí? –

+0

@dario_ramos No tengo idea, pero la respuesta de tus compañeros implica que puedes. –

1

¡Excelente pregunta! Puede simular una clase de Mapper creando una nueva que herede de la clase singleton Mapper y luego usarla para interceptar todas las llamadas a su base de datos.

Cuestiones relacionadas