Tengo un método DAO que utiliza Spring para el acceso JDBC. Calcula la tasa de éxito de un vendedor de vender un artículo.
Aquí está el código:
public BigDecimal getSellingSuccessRate(long seller_id) {
String sql = "SELECT SUM(IF(sold_price IS NOT NULL, 1, 0))/SUM(1)
FROM transaction WHERE seller_id = ?";
Object[] args = {seller_id};
return getJdbcTemplate().queryForObject(sql, args, BigDecimal.class);
}
¿Cómo debo probar este método o cualquier método DAO con JUnit? ¿Cuáles son algunas de las mejores prácticas para probar la lógica de acceso a datos? Estoy pensando en probarlo en una base de datos incorporable cargada con algunos datos, pero ¿no deberíamos hacer pruebas de integración similares a un entorno de producción en términos de RDBMS y el esquema?
java
programming-practices
testing
tdd
Miguel
fuente
fuente
Respuestas:
El problema con el uso de una base de datos 'real' para pruebas unitarias es la configuración, desmontaje y aislamiento de las pruebas. No desea tener que crear una base de datos MySQL completamente nueva y crear tablas y datos solo para una prueba unitaria. Los problemas con esto tienen que ver con la naturaleza externa de la base de datos y su base de datos de prueba está inactiva, sus pruebas unitarias fallan. También hay problemas para asegurarse de tener una base de datos única para realizar pruebas. Se pueden superar, pero hay una respuesta más simple.
Burlarse de la base de datos es una opción, sin embargo, no prueba las consultas reales que se ejecutan. Puede usarse como una solución mucho más simple cuando desea asegurarse de que los datos del DAO pasan por el sistema correctamente. Pero para probar el DAO en sí mismo, necesita algo detrás del DAO que tiene los datos y las consultas se ejecutan correctamente.
Lo primero que debe hacer es usar una base de datos en memoria. HyperSQL es una excelente opción para esto porque tiene la capacidad de emular el dialecto de otra base de datos, de modo que las pequeñas diferencias entre las bases de datos permanecen iguales (tipos de datos, funciones y similares). hsqldb también tiene algunas características interesantes para las pruebas unitarias.
Esto carga el estado de la base de datos (las tablas, los datos iniciales) del
testData
archivo.shutdown=true
cerrará automáticamente la base de datos cuando se cierre la última conexión.Utilizando la inyección de dependencia , haga que las pruebas unitarias seleccionen una base de datos diferente de la que usan las compilaciones de producción (o prueba o local).
Su DAO luego usa la base de datos inyectada para la cual puede iniciar pruebas contra la base de datos.
Las pruebas unitarias se verán así (un montón de cosas aburridas no incluidas por brevedad):
Y por lo tanto, tiene una prueba unitaria que llama al DAO y está utilizando los datos que se configuraron en una base de datos sobre la marcha que existe durante la duración de la prueba. No tiene que preocuparse por los recursos externos o el estado de la base de datos antes de la ejecución, o la restauración a un estado conocido (bueno, el "estado conocido" es "no existe", que es trivial para volver).
DBUnit puede hacer que gran parte de lo que describí sea un proceso más simple para configurar la base de datos, crear las tablas y cargar los datos. Si iba a necesitar usar la base de datos real por alguna razón, esta es, con mucho, la mejor herramienta para usar.
El código anterior es parte de un proyecto maven que escribí para la prueba de concepto TestingWithHsqldb en github
fuente
sql.syntax_mys=true
que cambian la forma en que funciona hsqldb: "Esta propiedad, cuando se establece como verdadera, habilita la compatibilidad con los tipos TEXT y AUTO_INCREMENT y también permite la compatibilidad con algunos otros aspectos de este dialecto". whilesql.syntax_ora=true
"Esta propiedad, cuando se establece como verdadera, permite la compatibilidad con tipos no estándar. También permite la sintaxis DUAL, ROWNUM, NEXTVAL y CURRVAL y también permite la compatibilidad con algunos otros aspectos de este dialecto".Primero, nunca debe hacer pruebas en un entorno de producción. Debe tener un entorno de prueba que refleje su entorno de producción y hacer pruebas de integración allí.
Si haces eso, entonces puedes hacer varias cosas.
fuente
En nuestro proyecto, cada desarrollador ejecuta una base de datos vacía, su estructura es la misma que la base de datos de producción.
En cada prueba unitaria TestInitialize, creamos una conexión y transacción con la base de datos más algunos objetos predeterminados que necesitamos para cada prueba. Y todo se revierte después del final de cada método o clase.
De esta manera, es posible probar la capa sql. De hecho, cada consulta o llamada a la base de datos debe probarse de esta manera.
La desventaja es que es lento, por lo que lo colocamos en un proyecto separado de nuestras pruebas unitarias regulares. Es posible acelerar esto usando una base de datos en memoria, pero la idea sigue siendo la misma.
fuente