Un ejemplo de un caso de falla que prefieres atrapar, es que el objeto bajo prueba utiliza una capa de almacenamiento en caché, pero no logra conservar los datos según sea necesario. Luego, si consulta el objeto, dirá "sí, tengo el nuevo nombre y la nueva dirección", pero desea que la prueba falle porque en realidad no hizo lo que se suponía.
Alternativamente (y pasando por alto la violación de responsabilidad única), supongamos 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 los volverá a convertir desde Shift JIS, pero su prueba no detectó el error. Es de esperar que se detecte en una prueba de integración posterior, pero el objetivo principal 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, su propio caso de prueba fallará y podremos arreglarlo y ejecutar la batería de prueba nuevamente.
No puedes asumir esto, porque si no tienes cuidado, escribe un conjunto de pruebas mutuamente dependientes. El "ahorra?" prueba llama al método de guardar que está probando, y luego el método de carga para confirmar que se guardó. El "se carga?" prueba llama al método de guardar para configurar el dispositivo de prueba y luego el método de carga que está probando para verificar el resultado. Ambas pruebas se basan en la corrección del método que no están probando, lo que significa que ninguna de ellas realmente prueba la corrección del método que está probando.
La clave de que hay un problema aquí es que dos pruebas que supuestamente están probando diferentes unidades 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 establecedor persiste en los datos, no que el par de establecedor / getter funcione en conjunto. Entonces, sabes que algo está mal, solo tienes que averiguar qué y corregir las pruebas.
Si su código está bien diseñado para la prueba de unidad, entonces hay al menos dos formas de probar si el método bajo prueba realmente ha persistido correctamente en los datos:
-
simula la interfaz de la base de datos y haz que tu simulacro registre el hecho de que se han activado 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.
-
pásele 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. Es posible que esta no sea la prueba más pura posible, porque un motor de base de datos completo es algo muy importante para escribir un simulacro glorificado, con más posibilidades de que pase por alto alguna sutileza que hace que una prueba pase, aunque sea algo está mal (por ejemplo, no debería usar la misma conexión de base de datos para leer que la que se usó para escribir, porque es posible que vea 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.
Así que es un mero detalle de la implementación de 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 mejor la unidad aislándola que puedo si permito que conspire con otros métodos incorrectos en la misma clase para que se vean bien, incluso cuando algo está mal. Por lo tanto, quiero utilizar cualquier medio conveniente para verificar que los datos correctos se mantuvieron, aparte de confiar en el componente cuyo método estoy probando.
Si su código no está bien diseñado para pruebas de unidad, 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 sometida a prueba, se convierte en una discusión acerca de qué tan cerca es posible aislar la unidad sometida a prueba. Sin embargo, la conclusión es la misma. Si puede evitar las conspiraciones entre unidades defectuosas, entonces lo hace, sujeto al tiempo disponible y cualquier otra cosa que piense que sería más eficaz para encontrar fallas en el código.