2009-07-12 20 views
5

Estoy empezando a probar las unidades y revisar la programación web de Java. La cuestión es que no sé si estoy haciendo las cosas bien.Pruebas unitarias DAO, ¿lo estoy haciendo bien?

Estoy construyendo un mini blog. Estoy usando EasyMock para los objetos simulados.

Aquí está mi código:

The test case

The PostDAO

The Post Bean

Te lo agradecería sus comentarios y sugerencias sobre cómo podría mejorar mi código y convertirse en un mejor programador. ¡Gracias por adelantado!

+7

Los enlaces pastebin están muertos. –

+2

sin los enlaces, esta pregunta pierde sentido. – Asgaroth

+0

Difícil de seguir sin ningún código ... –

Respuesta

24

Aquí hay algunas ideas para una revisión de minicódigo. Tómalos por lo que valen, simplemente no te ofendas:

  1. Deberías estar usando el idioma de JUnit 4.x. No es necesario extender TestCase. Use las anotaciones "@Test".
  2. Burlarse de la conexión para el DAO es ridículo. Use una conexión real, conéctese a la base de datos y ejecute consultas reales. Sin eso, tu prueba DAO no tiene valor.
  3. Falta una de las consideraciones más importantes cuando se prueban los DAO: los datos. Su configuración, tal como está escrita, no está ayudando. Lo que realmente quieres es crear una base de datos con datos de prueba, ejecutar tus pruebas y luego retrotraer todo para que sea como si nunca hubieras estado allí. Uno de los mayores problemas con las bases de datos de prueba es asegurarse de que los datos de prueba estén disponibles. Hacer las cosas como una transacción es la mejor manera de lograrlo.
  4. Estás probando el "camino feliz", pero no estás probando ninguna condición de borde en absoluto. Cada uno debe ser una llamada de prueba por separado. No puedo ver su esquema, pero si su tabla prohíbe valores nulos para cualquiera de los parámetros, o impone una restricción única, escribiría pruebas separadas para cada uno para demostrar ese hecho y para demostrar que funciona correctamente. ¿Cuál es el enfoque correcto para manejarlos? Lanzar una excepción? Deberías pensar en eso.
  5. Su manejo de errores es pobre. Imprimir un mensaje a la consola no es útil. Al menos debe iniciar sesión usando log4j.
  6. Su método createPost parece fuera de base. Pasas dos parámetros y devuelves una publicación. Por lo general, con soluciones ORM, como Hibernate, ya tendrás objetos en su lugar.
  7. Los DAO no deberían estar creando Conexiones. Deben ser transferidos por una capa de servicio que conoce las unidades de trabajo y las transacciones.
  8. Hablando de eso, no tiene una lógica de compromiso/retrotracción. Gracias a Dios, porque no pertenece a un DAO, pero apuesto a que no lo has pensado.
  9. Parece que quiere decir que "id" es una clave principal, pero no veo nada que extraer de la base de datos después de INSERTAR y llenar el objeto. No sucederá solo.
  10. Aprenderá mucho mirando Spring's Compatibilidad con JDBC. Lo recomendaría. Lo han hecho mejor de lo que nunca lo harás.
+0

10. ¿Crees que debería intentar bucear en Spring? De hecho, es mi verdadero objetivo aprenderlo. Solo estoy haciendo el mini blog como práctica. Gracias especiales a duffymo por su paciencia y su ayuda. Gracias :) – user133127

+3

Sí, puedo recomendar Spring de todo corazón. No te preocupes por tragar todo de una vez. Puedes hacerlo en pedazos. Comience con el soporte JDBC y trabaje para salir. – duffymo

+1

duffymo, si usamos una conexión real a DB, ¿sigue siendo esta una prueba unitaria? Pensé que se convertiría en la prueba de integración, ¿no es así? – shevchyk

2

No está relacionado con las pruebas de su unidad, pero consideraría su manejo de excepciones en malas prácticas de createPost (..). La excepción no se traga por completo, pero devolver un objeto Post como si todo hubiera ido bien no es una buena idea. Ver Error Hiding

+0

Tienes razón, gracias por señalar :) – user133127

1

Creo que está generalmente bien (introduciría una constante de cadena para su SQL para evitar repetirlo, por cierto).

Por supuesto, la única cosa que no está probando con esto es la interacción real con la base de datos (ya que esto se está burlando). Entonces, ¿esperaría una prueba correspondiente (o un conjunto de?) Que en realidad interactúe con la base de datos, e inserte/replique según corresponda. De lo contrario, estás probando algo que (en este momento) es bastante trivial.

Una nota sobre la organización de la prueba. A continuación, se prueban 2 cosas (la construcción nula falla y la construcción normal tiene éxito). Yo dividiría esto en dos pruebas, de lo contrario, si la primera sección falla, nunca prueba la segunda sección (en escenarios más complejos, esto hace que el diagnóstico de fallas sea más difícil, ya que puede no tener tanta evidencia como necesite)

public void testPostDAO() { 
     try { 
       new PostDAO(null); 
       fail("Expected IllegalArgumentException"); 
     } catch (IllegalArgumentException ex) {} 
     new PostDAO(connectionMock); 
} 

Algunas personas se oponen a la prueba new PostDAO(null) debido a su trivialidad. Estoy en desacuerdo. Una de las razones por las que escribe las pruebas es para garantizar que el comportamiento de no cambie a menos que lo espere al. Entonces, lo anterior es bueno. Simplemente lo dividiría en dos pruebas explícitas.

+0

>> Presentaría una constante de cadena ¿Y luego qué hará esta prueba? ¿Entonces malinterpretaste "insart" y ...? –

+0

Introduzca una constante de cadena para evitar repetirla y tener valores inconsistentes/engañosos? Me parece una buena práctica bastante obvia y normal –

+0

Si vas a rechazar las respuestas, ¿puedes indicar por qué? No creo que haya nada particularmente incorrecto/contencioso/fuera de tema en lo anterior, ¿verdad? –

1

Algunos pensamiento de beginnig de la prueba:

public void testPostDAO() { 
       try { 
         new PostDAO(null); 
         fail("Expected IllegalArgumentException"); 
       } catch (IllegalArgumentException ex) {} 
       new PostDAO(connectionMock); 
     } 

siguientes cambios no son obligatorias y alguien puede dijeron que están mal, pero es mi opinión:

  1. caso normal de Split y el error - - que son dos comportamientos diferentes de su unidad bajo prueba

  2. Cambie el nombre a algo más claro - para especificar lo que está haciendo - por ejemplo testPostDAOWithNullArg

  3. Su prueba falla si no se plantea ninguna excepción, ¿qué tal si se levanta la excepción WeryBadStange? No lo agarrarás, y no llegarás a fallar la línea.
+0

Si se lanza VeryBadStrangeException, ¿no tiene que verificarse o se lanzará desde la prueba y desencadenará un error? –

+0

Sí, realmente verás que algo falló :) Pero prefiero comprobarlo - algo así como - fallar ("Expected Exception1 pero obtuvo Exception2") en mi marco de pruebas de unidad me da una prueba fallida y una mejor comprensión de El problema es que si recibo un extraño mensaje de excepción y una prueba de error. –

+0

Sí. Comprobar que se ha lanzado una excepción explícita es definitivamente una buena idea –

2
  • ¿Qué estás haciendo aquí?En mi humilde opinión, lo único importante aquí es su comando SQL ya que no hay una lógica específica para probar en su DAO.
  • Probar el código de inicio como "nuevo PostDAO (nulo)" es inútil cuando es tan simple.
  • Preferiría hsqldb en modo de memoria para probar contra una base de datos real y tener menos código falso.
  • ¿Hay alguna razón por la que no pueda usar el estilo de prueba JUnit 4 usando la anotación en lugar de extender TestCase como en JUnit 3?
+0

1. Estoy probando toda la clase. Estoy confundido, ¿cómo sé si tengo que probar un componente de mi programa o no? 3. Ok, voy a sumergirme en hsqldb siguiente :) 4. De hecho, todos los tutoriales que estoy leyendo enseñan JUnit 3. ¿Hay muchas razones de peso para cambiar a JUnit 4? – user133127

+0

Por cierto, ¿podría indicarme la dirección correcta sobre cómo probar la unidad con hsqldb? :) – user133127

+0

Las preguntas que me hago son: ¿Cuánta confianza me dan las pruebas? ¿Qué no están atrapando? En PostAprobado, si escribió mal el nombre de una columna de base de datos en el código y también en la prueba, la prueba pasaría pero el código tendría un error. Los simulacros pueden ser útiles, pero solo son tan buenos como las expectativas que les estableces. Una base de datos es lo suficientemente complicada como para que sea muy fácil equivocar esas expectativas. Use una base de datos en memoria como hsqldb para sus pruebas DAO y se burla de las clases que hablan con los DAO. – NamshubWriter

1

No hay ningún punto en su Prueba de unidad en absoluto. ¿Qué estás probando? ¿Qué lógica tienes? ¿Qué prueba?

Veo que sus pruebas no prueban nada. El inserto con mecanografía Miss pasará su prueba. Argumentos inválidos también

Creo que aquí debería usar la integración o las pruebas funcionales. Usa una base de datos real. Esto hará que tus pruebas sean mucho más livianas, además esto probará tu código y, lo que es más importante, demostrará que tu código es correcto.

+0

Hola Mike, ¿cómo sé si tengo que probar una parte de mi programa o no? – user133127

+0

Si te refieres a la cobertura de códigos, todo está bien aquí. Simplemente ejecute pruebas funcionales y unitarias en una sola sesión. Por ejemplo, tenemos una "Integración" de categoría especial que marca las pruebas que acceden a la base de datos. Entonces, para el trabajo regular simplemente desactivamos las pruebas con esta categoría. Y solo ejecuta sute completo cuando sea necesario. También nuestro servidor de CI ejecuta un conjunto completo. ¿Tiene sentido? –

Cuestiones relacionadas