2011-08-22 17 views
11

La pregunta más completa es, dada una dependencia que espera una devolución de llamada como parámetro, ¿cómo puedo escribir una prueba de unidad que cubra la lógica de devolución de llamada y que aún logran simular la dependencia?Cómo probar la unidad de lógica de devolución de llamada?

public class DoStuff { 
    public void runThis(Runnable callback) { 
     // call callback 
    } 
} 

public class ClassUnderTest { 
    private DoStuff stuffToDo; 

    public void methodUnderTest() { 
     this.stuffToDo.runThis(/*a runnable with some logic*/) 
    } 
} 

En el ejemplo anterior, me gustaría burlarse stuffToDo ya que debería verificar las llamadas y los resultados simulados de llamadas a métodos. Sin embargo, burlarse de runThis hace que la lógica de devolución de llamada no se pruebe. Además, la lógica de devolución de llamada parece que debería ser privada, por lo que no esperaría probarla directamente; quizás eso es una idea errónea de mi parte.

Dado que las devoluciones de llamada se utilizan bastante extensivamente, esperaría que hubiera un método común para probarlas pero no las he encontrado.

+0

¿Es necesario probar la devolución de llamada solo en este contexto? Si es así, ¿por qué no simplemente escribir pruebas para las distintas devoluciones de llamada que planea pasar, que expresan su expectativa de los resultados? ¿Me estoy perdiendo de algo? – Jonah

+0

Ha intentado usar CountDownLatch como en este ejemplo: http://stackoverflow.com/a/3802487/2301224 – Baker

Respuesta

10

No se puede en una sola prueba. Si se burla de algo, es el que se burló de, lo que significa que solo puede verificar los argumentos y simular los valores de retorno (que configura en la prueba).

De hecho, todo el punto de burlarse de algo es probar lo que utiliza el simulacro de forma aislada. Si desea una prueba de unidad de DoStuff, no desea tener que preocuparse por utilizar alguna implementación de devolución de llamada que podría o no funcionar. Te burlas de la devolución de llamada por lo que no tienes que preocuparte por eso.

Puede todavía tienen buenas pruebas de verificación del código de devolución de llamada de forma aislada, y probando el usuario de devolución de llamada de forma aislada (usando una maqueta para la devolución de llamada) y tal vez lanzando una prueba de integración en una buena medida, en el que utiliza el componente completamente configurado como un todo.

1

Aquí, básicamente, desea probar la clase DoStuff. Eso significa que necesita probar todos los métodos dentro de DoStuff, ¿verdad ?. Entonces, en este caso, lo que debe hacer es, en lugar de burlarse de stuffToDo en sí, inyectar un Runnable simulado en stuffToDo. Y luego verifique si su ejecutable se ejecutó correctamente o no.

Pero si tiene otras funcionalidades en la clase, puede tener una prueba por separado y simularlas.

+1

Quiero probar ClassUnderTest que toma DoStuff como una dependencia. –

0

En su caso particular, parece que ya ha probado DoStuff (o ya no le importo ya que se burla) y ahora están específicamente probando la unidad de un Runnable específico que haya diseñado. En este caso, callback suena exactamente como lo que quiere probar, de la misma manera que alguien querría probar específicamente una estrategia de base de datos o una estrategia en memoria directamente.

Si esto es lo que está intentando, puede probarlo en una caja negra, ejercitándolo a través de ClassUnderTest lo mejor que pueda. O puede crear un arnés de prueba en su Runnable particular. Si está liberando este código y no desea que su arnés de prueba sea alcanzable, puede hacer que los métodos de arnés de prueba sean privados y compartir sus detalles específicamente con el ensamblaje de prueba de su unidad.

Mire here para obtener información acerca de cómo hacer ensamblajes amigos. Normalmente firmo el código de mi unidad de prueba para no tener que ensuciar con un compilador de línea de comandos. Supongo que depende de tu entorno de construcción.

+0

No, ClassUnderTest es la clase que se probará. Me estoy burlando de DoStuff. –

+0

Modifiqué el nombre de la clase para reflejar esto. No afecta la respuesta. –

0

Si usa EasyMock, puede usar andStubAnswer para llamar al ejecutable.

doSomethingMock.runThis(runnable); 
expectLastCall().andStubAnswer(new IAnserable<Void>() { 
    Runnable runnable = (Runnable)getCurrentArguments()[0]; 
    runnable.run(); 
    return null; 
}); 

Imagino que otros marcos burlones contienen algo similar.

0

¿Qué tal una DoStuff falsa que solo invoca Runnable incondicionalmente?

Luego solo detecta los efectos: cambios que se deben observar si se ejecutó la devolución de llamada.

Cuestiones relacionadas