Las pruebas de JDBC deben usar una base de datos real (o embebida H2 en modo MySQL), no mocks. Los mocks de JDBC raramente detectan errores reales del driver o de las constraints de la BD.
Test de integración con JUnit 5 y H2
import org.junit.jupiter.api.*;
import static org.junit.jupiter.api.Assertions.*;
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
class ProductoDaoJdbcTest {
static DataSource ds;
static ProductoDao dao;
@BeforeAll
static void configurar() throws Exception {
HikariConfig cfg = new HikariConfig();
cfg.setJdbcUrl("jdbc:h2:mem:test;DB_CLOSE_DELAY=-1;MODE=MySQL");
cfg.setUsername("sa"); cfg.setPassword("");
ds = new HikariDataSource(cfg);
// Crear esquema
try (Connection c = ds.getConnection(); Statement st = c.createStatement()) {
st.execute("CREATE TABLE productos (id INT AUTO_INCREMENT PRIMARY KEY, nombre VARCHAR(100) NOT NULL, precio DOUBLE NOT NULL, activo BOOLEAN DEFAULT TRUE)");
}
dao = new ProductoDaoJdbc(ds);
}
@Test @Order(1)
void guardar_y_recuperar_por_id() {
Producto p = new Producto("Ratón óptico", 29.99);
int id = dao.save(p);
assertTrue(id > 0);
Optional<Producto> recuperado = dao.findById(id);
assertTrue(recuperado.isPresent());
assertEquals("Ratón óptico", recuperado.get().nombre());
assertEquals(29.99, recuperado.get().precio(), 0.001);
}
@Test @Order(2)
void actualizar_producto() {
Producto original = new Producto("Viejo nombre", 10.0);
int id = dao.save(original);
Producto actualizado = new Producto(id, "Nuevo nombre", 15.0, true);
boolean ok = dao.update(actualizado);
assertTrue(ok);
Producto leido = dao.findById(id).orElseThrow();
assertEquals("Nuevo nombre", leido.nombre());
}
@Test @Order(3)
void eliminar_producto() {
Producto p = new Producto("Borrar esto", 5.0);
int id = dao.save(p);
assertTrue(dao.delete(id));
assertFalse(dao.findById(id).map(Producto::activo).orElse(true));
}
@AfterAll
static void limpiar() throws Exception {
((HikariDataSource) ds).close();
}
}
