Un ejemplo de un caso de falla que preferiría detectar, es que el objeto bajo prueba usa una capa de almacenamiento en caché pero no persiste los datos según sea necesario. Luego, si consulta el objeto, dirá "sí, tengo el nuevo nombre y dirección", pero desea que la prueba falle porque en realidad no ha hecho lo que se suponía que debía hacer.
Alternativamente (y pasando por alto la violación de responsabilidad única), suponga que se requiere que persista una versión codificada en UTF-8 de la cadena en un campo orientado a bytes, pero en realidad persiste Shift JIS. Algún otro componente leerá la base de datos y espera ver UTF-8, de ahí el requisito. Luego, el viaje de ida y vuelta a través de este objeto informará el nombre y la dirección correctos porque lo convertirá de nuevo desde Shift JIS, pero su prueba no detecta el error. Es de esperar que sea detectado por alguna prueba de integración posterior, pero el objetivo de las pruebas unitarias es detectar los problemas temprano y saber exactamente qué componente es responsable.
Si uno de ellos no está haciendo lo que se supone que debe hacer, entonces su propio caso de prueba fallará y podemos arreglarlo y volver a ejecutar la batería de prueba.
No puede asumir esto, porque si no tiene cuidado, escribe un conjunto de pruebas mutuamente dependientes. El "¿salva?" prueba llama al método de guardar que está probando, y luego al método de carga para confirmar que está guardado. El "¿se carga?" test llama al método save para configurar el dispositivo de prueba y luego al método de carga que está probando para verificar el resultado. Ambas pruebas se basan en la exactitud del método que no están probando, lo que significa que ninguno de ellos prueba realmente la exactitud del método que está probando.
La pista de que hay un problema aquí es que dos pruebas que supuestamente están probando unidades diferentes en realidad hacen lo mismo . Ambos llaman a un setter seguido de un getter, luego verifican que el resultado sea el valor original. Pero quería probar que el setter persiste los datos, no que el par setter / getter trabaje en conjunto. Entonces, sabes que algo anda mal, solo tienes que averiguar qué y arreglar las pruebas.
Si su código está bien diseñado para pruebas unitarias, entonces hay al menos dos formas en que puede probar si los datos realmente han sido conservados correctamente por el método bajo prueba:
simule la interfaz de la base de datos y haga que su simulacro registre el hecho de que se han llamado a las funciones adecuadas con los valores esperados. Esto prueba que el método hace lo que se supone que debe hacer, y es la prueba unitaria clásica.
pasarle una base de datos real con exactamente la misma intención , para registrar si los datos se han conservado correctamente o no. Pero en lugar de tener una función simulada que simplemente dice "sí, obtuve los datos correctos", su prueba se lee directamente de la base de datos y confirma que es correcta. Puede que esta no sea la prueba más pura posible, porque un motor de base de datos completo es bastante importante para escribir un simulacro glorificado, con más posibilidades de que pase por alto alguna sutileza que haga pasar una prueba aunque algo esté mal (por ejemplo, yo no debería usar la misma conexión de base de datos para leer que se usó para escribir, porque podría ver una transacción no confirmada). Pero prueba lo correcto, y al menos sabes que precisamente implementa toda la interfaz de la base de datos sin tener que escribir ningún código simulado.
Por lo tanto, es un simple detalle de la implementación de la prueba si leo los datos de la base de datos de prueba por JDBC o si me burlo de la base de datos. De cualquier manera, el punto es que puedo probar la unidad mejor aislándola que si puedo permitir que conspire con otros métodos incorrectos en la misma clase para que se vea bien, incluso cuando algo está mal. Por lo tanto, quiero usar cualquier medio conveniente para verificar que los datos correctos persistieron, aparte de confiar en el componente cuyo método estoy probando.
Si su código no está bien diseñado para pruebas unitarias, es posible que no tenga otra opción, ya que el objeto cuyo método desea probar podría no aceptar la base de datos como una dependencia inyectada. En cuyo caso, la discusión sobre la mejor manera de aislar la unidad bajo prueba, se convierte en una discusión sobre qué tan cerca es posible aislar la unidad bajo prueba. Sin embargo, la conclusión es la misma. Si puede evitar conspiraciones entre unidades defectuosas, lo hace, sujeto al tiempo disponible y a cualquier otra cosa que piense que sería más eficaz para encontrar fallas en el código.