2012-05-12 9 views
6

estoy familiarizado con los principios básicos de TDD, siendo:¿Cuál es el mejor enfoque para las pruebas unitarias cuando tiene interfaces con implementaciones ficticias y reales?

  1. pruebas de escritura, éstas fallarán debido a la falta de aplicación
  2. Escribir implementación básica para que pasen las pruebas
  3. código Refactor

Sin embargo, estoy un poco confundido acerca de dónde encajan las interfaces y la implementación. Estoy creando una aplicación web Spring en mi tiempo libre, y en lugar de ir en armas, me gustaría entender cómo puedo probar interfaces/implementaciones un poco mejor, tome este código de ejemplo simple que he creado aquí:

public class RunMe 
{ 

    public static void main(String[] args) 
    { 
     // Using a dummy service now, but would have a real implementation later (fetch from DB etc.) 
     UserService userService = new DummyUserService(); 
     System.out.println(userService.getUserById(1)); 
    } 
} 

interface UserService 
{ 
    public String getUserById(Integer id); 
} 

class DummyUserService implements UserService 
{ 
    @Override 
    public String getUserById(Integer id) 
    { 
     return "James"; 
    } 
} 

he creado la interfaz UserService, en última instancia, habrá una aplicación real de este que va a consultar una base de datos, sin embargo, con el fin de conseguir la aplicación de la tierra que he sustituido una implementación DummyUserService que se acaba de regreso algunos datos estáticos por ahora.

Pregunta: ¿Cómo puedo poner en práctica una estrategia de ensayo de lo anterior?

que podría crear una clase de prueba llamada DummyUserServiceTest y la prueba de que cuando llamo getUserById() se volverá James, parece bastante simple si no es una pérdida de tiempo (?).

Posteriormente, yo también podría crear una clase de prueba RealUserService que probaría que getUserById() devuelve un nombre de usuario de la base de datos. Esta es la parte que me confunde levemente, al hacerlo, ¿no se sobrepasa el límite de una prueba unitaria y se convierte más en una prueba de integración (con el acierto en la base de datos)?

Pregunta (mejorado, un poco): Cuando se utilizan interfaces con dummy/stubbed, y las implementaciones reales, ¿qué partes deben probarse unitarias, y qué partes pueden dejarse sin probar?

pasé unas cuantas horas de buscar en Google sobre este tema anoche, y sobre todo encontrar ya sea tutoriales sobre lo que es TDD, o ejemplos de cómo utilizar JUnit, pero nada en los reinos de asesorar a lo que realmente debe hacerse la prueba. Sin embargo, es muy posible que no haya buscado lo suficiente o que no esté buscando lo correcto ...

Respuesta

4

No pruebe las implementaciones ficticias: no se usarán en producción. No tiene sentido probarlos.

Si la implementación real UserService no hace nada más que ir a una base de datos y obtener el nombre de usuario por su ID, la prueba debe probar que lo hace y lo hace correctamente. Llámelo una prueba de integración si lo desea, pero es una prueba que debe escribirse y automatizarse.

La estrategia habitual es rellenar la base de datos con datos de prueba mínimos en el método anotado @Before de la prueba, y hacer que el método de prueba verifique que exista un nombre de usuario correspondiente en la base de datos.

0

La respuesta de JB es buena, pensé que descartaría otra técnica que he usado.

Al desarrollar la prueba original, no se moleste en anular el UserService en primer lugar. De hecho, adelante y escriba lo real. Siga por el siguiente Kent Beck's 3 rules.

1) Haga que funcione. 2) Hazlo bien. 3) Hazlo rápido.

Su código tendrá pruebas que luego verificará que funciona el find by id. Como JB declaró, sus pruebas se considerarán Pruebas de integración en este punto. Una vez que están pasando, hemos logrado con éxito el paso 1. Ahora, mira el diseño. ¿Es correcto? Modifique los olores de diseño y marque el paso 2 de su lista.

Para el paso 3, tenemos que hacer esta prueba rápidamente. Todos sabemos que las pruebas de integración son lentas y propensas a errores con todas las configuraciones de bases de datos y administración de transacciones. Una vez que sabemos que el código funciona, normalmente no me molesto con las pruebas de integración. Es en este momento donde puede presentar su servicio ficticio, convirtiendo efectivamente su prueba de integración en una prueba unitaria. Ahora que no toca la base de datos de ninguna manera, podemos verificar el paso 3 de la lista porque esta prueba ahora es rápida.

Entonces, ¿cuáles son los problemas con este enfoque? Bueno, muchos dirán que todavía necesito una prueba para la base de datos respaldada UserService. Normalmente no mantengo las pruebas de integración en mi proyecto. Mi opinión es que este tipo de pruebas son lentas, frágiles y no detectan suficientes errores lógicos en la mayoría de los proyectos para pagarse por sí mismos.

Espero que ayude!

Brandon

3

Yo recomendaría que lea este libro primero: Growing Object-Oriented Software Guided by Tests por Steve Freemand y Nat Pryce. Responde su pregunta y muchas otras relacionadas con TDD.

En su caso particular, debe configurar su RealUserService configurable con un adaptador de base de datos, lo que hará que las consultas DB reales. El servicio en sí será el servicio, no la persistencia de datos. Lea el libro, ayudará mucho :)

Cuestiones relacionadas