El problema de usar H2 para pruebas
Una práctica común es utilizar bases de datos ligeras como H2 o HSQL como bases de datos en memoria para pruebas, mientras se utiliza PostgreSQL, MySQL u Oracle en producción. Este enfoque presenta desventajas significativas:
- Es posible que la base de datos de pruebas no admita todas las características de tu base de datos de producción.
- La sintaxis SQL puede no ser compatible entre H2 y tu base de datos de producción.
- El hecho de que las pruebas pasen con H2 no garantiza que vayan a funcionar en producción.
Ejemplo: Sintaxis específica de PostgreSQL
Considera la implementación de un "upsert" (insertar un producto solo si aún no existe). En PostgreSQL, puedes utilizar:
INSERT INTO products(id, code, name) VALUES(?,?,?) ON CONFLICT DO NOTHING;Esta consulta no funciona con H2 de forma predeterminada:
Caused by: org.h2.jdbc.JdbcSQLException: Syntax error in SQL statement
"INSERT INTO products (id, code, name) VALUES (?, ?, ?) ON[*] CONFLICT DO NOTHING";Puedes ejecutar H2 en modo de compatibilidad con PostgreSQL, pero no se admiten
todas las características. Lo contrario también es cierto: H2 admite ROWNUM(),
algo que PostgreSQL no hace.
Realizar las pruebas con una base de datos diferente a la de producción significa que no puedes confiar plenamente en los resultados de tus pruebas y debes realizar verificaciones después del despliegue, lo que anula el propósito de las pruebas automatizadas.
La prueba de Spring Boot utilizando H2
Una prueba típica basada en H2 se ve así:
@DataJpaTest
class ProductRepositoryTest {
@Autowired
ProductRepository productRepository;
@Test
@Sql("classpath:/sql/seed-data.sql")
void shouldGetAllProducts() {
List<Product> products = productRepository.findAll();
assertEquals(2, products.size());
}
}Spring Boot utiliza H2 automáticamente cuando se encuentra en el classpath. La prueba pasa, pero no detecta los problemas específicos de PostgreSQL.