# 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:

```sql
INSERT INTO products(id, code, name) VALUES(?,?,?) ON CONFLICT DO NOTHING;
```

Esta consulta no funciona con H2 de forma predeterminada:

```text
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í:

```java
@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.

