2008-09-18 13 views
6

¿Hay alguna manera de burlarse de la construcción de objetos usando JMock en Java?¿Cómo burlarse de la construcción de objetos?

Por ejemplo, si tengo un método como tal:

public Object createObject(String objectType) { 
    if(objectType.equals("Integer") { 
     return new Integer(); 
    } else if (objectType.equals("String") { 
     return new String(); 
    } 
} 

... ¿hay una manera de burlarse de la expectativa de la construcción objeto en un método de prueba?

Me gustaría poder establecer las expectativas de que se están llamando a ciertos constructores, en lugar de tener un código adicional para verificar el tipo (ya que no siempre será tan intrincado y simple como mi ejemplo).

Así que en lugar de:

assertTrue(a.createObject() instanceof Integer); 

que podría tener una expectativa cierta de la constructora que se llama. Solo para que sea un poco más limpio, y expresar lo que realmente se está probando de una manera más legible.

Por favor, disculpe el ejemplo sencillo, el problema real que estoy trabajando es un poco más complicado, pero tener la expectativa sería simplificarlo.


Por un poco más de fondo:

que tienen un método de fábrica sencillo, lo que crea objetos envolventes. Los objetos que se envuelven pueden requerir parámetros que son difíciles de obtener en una clase de prueba (es un código preexistente), por lo que es difícil construirlos.

Tal vez más cerca de lo que realmente estoy buscando es: ¿hay alguna manera de burlarse de una clase completa (usando CGLib) de un solo golpe, sin especificar cada método para anular?

Así que la maqueta se está envuelto en un constructor, por lo que, obviamente, los métodos pueden ser llamados en él, es capaz de dinámicamente JMock burla a cabo cada método?

Supongo que no, ya que sería bastante complicado. Pero saber que estoy ladrando al árbol equivocado es valioso también :-)

+0

Usted es la fábrica podría tener su fábricas propias para cada tipo podría construir (una fábrica de enteros, una fábrica de cuerdas, etc) pero, tienes razón, eso es virar hacia excesivamente complicado . Es probable que la prueba de prueba sea probablemente la mejor opción. – sblundy

Respuesta

5

Lo único que se me ocurre es tener el método de creación en el objeto de fábrica, que se burlaría.

Pero en términos de burlarse de una llamada de constructor, no. Los objetos simulados presuponen la existencia del objeto, mientras que un constructor presupone que el objeto no existe. Al menos en Java donde la asignación y la inicialización suceden juntas.

-1

espero que no la hay. Se supone que los simuladores simulan interfaces, que no tienen constructores ... solo métodos.

Algo parece estar mal en su acercamiento a probar aquí. ¿Alguna razón por la que necesita probar que se están llamando a constructores explícitos?
La afirmación del tipo de objeto devuelto parece estar bien para probar las implementaciones de fábrica. Trate createObject como blackbox ... examine lo que devuelve, pero no microgestión de cómo lo hace. A nadie le gusta eso :)

Actualización sobre la actualización: ¡Ay! Medidas desesperadas para tiempos desesperados ¿eh? Me sorprendería si JMock lo permite ... como dije, funciona en interfaces ... no en tipos concretos. Así

  • o bien tratar y gastar un poco de esfuerzo en conseguir 'instanciable' los objetos de entrada molestos bajo el instrumento de prueba. Ir hacia abajo en su enfoque.
  • Si eso no es factible, pruébela manualmente con puntos de interrupción (sé que es una mierda). Luego agregue un comentario de "Tóquelo bajo su propio riesgo" en una zona visible en el archivo fuente y avance. Pelea otro día
+0

Es un método simple de fábrica. El problema es que la fábrica crea envoltorios para otros objetos (tomándolos como un parámetro durante la construcción) y los devuelve. Me gustaría poder probar que se está llamando al constructor, en lugar de burlarse o crear una instancia del objeto que se está envolviendo. – Grundlefleck

+0

El problema es que el método de fábrica toma un objeto que es difícil de recrear de forma aislada, refactorizar para permitir que sea prácticamente imposible por el momento. Aunque ... burlarse de ellos es probablemente la respuesta ... – Grundlefleck

0

¿Está familiarizado con Dependency Injection?

Si no, entonces ceartanly se beneficiaría de aprender sobre ese concepto. Creo que el buen viejo Inversion of Control Containers and the Dependency Injection pattern de Martin Fowler servirá como una buena introducción.

Con Dependency Injection (DI), tendría un objeto contenedor DI, que es capaz de crear todo tipo de clases para usted. Entonces su objeto haría uso del contenedor DI para instanciar clases y se burlaría del contenedor DI para probar que la clase crea instancias de clases esperadas.

0

Dependencia de inyección o inversión de control.

Como alternativa, utilice el patrón de diseño Abstract Factory para todos los objetos que cree. Cuando esté en el modo de Prueba de Unidad, inyecte una Fábrica de Pruebas que le dirá qué está creando, luego incluya el código de afirmación en Fábrica de Pruebas para verificar los resultados (inversión del control).

Para dejar su código lo más limpio posible, cree una interfaz interna protegida, implemente la interfaz (su fábrica) con el código de producción como clase interna. Agregue un tipo de variable estática de su interfaz inicializada a su fábrica predeterminada. Agregue setter estático para la fábrica y listo.

En su código de prueba (debe estar en el mismo paquete, de lo contrario la interfaz interna debe ser pública), cree una clase anónima o interna con el código de confirmación y el código de prueba. Luego, en su prueba, inicialice la clase objetivo, asigne (inyecte) la fábrica de prueba y ejecute los métodos de su clase objetivo.

1

Por desgracia, creo que soy culpable de hacer la pregunta incorrecta.

El simple fábrica que estaba tratando de prueba se veía algo así como:

public Wrapper wrapObject(Object toWrap) { 
    if(toWrap instanceof ClassA) { 
     return new Wrapper((ClassA) toWrap); 
    } else if (toWrap instanceof ClassB) { 
     return new Wrapper((ClassB) toWrap); 
    } // etc 

    else { 
     return null; 
    } 
} 

que estaba pidiendo la pregunta de cómo encontrar si fue llamado "() nueva ClassAWrapper" porque el toWrap objeto era difícil de obtener en una prueba aislada. Y el contenedor (si es que se lo puede llamar así) es un poco extraño ya que usa la misma clase para envolver diferentes objetos, solo usa diferentes constructores [1]. Sospecho que si hubiera hecho la pregunta un poco mejor, habría recibido rápidamente la respuesta:

"Debería burlarse de Object toWrap para que coincida con las instancias que está probando en diferentes métodos de prueba e inspeccionar el Wrapper resultante objeto para encontrar el tipo correcto se devuelve ... y espero que tenga la suerte de que no tiene que burlarse del mundo para crear las diferentes instancias ;-) "

Ahora tengo una solución adecuada para el problema inmediato, gracias!

[1] la apertura de la cuestión de si esto debe ser rediseñado está bien fuera del alcance de mi problema actual :-)

Cuestiones relacionadas