Introducción
En este tutorial, vamos a crear una aplicación sencilla en Spring que dependa de una base de datos en memoria para realizar pruebas. En los entornos de desarrollo y testeos, es esencial tener un entorno de base de datos que no requiera demasiada configuración, y una base de datos en memoria como H2 puede ser la solución perfecta. Para el perfil estándar, la aplicación contará con una configuración de base de datos MySQL, que requiere la instalación y ejecución del servidor MySQL, junto con una configuración adecuada de usuario y base de datos. Sin embargo, para facilitar las pruebas, pasaremos de lado esta configuración adicional y utilizaremos una base de datos H2 en memoria para ejecutar las pruebas con JUnit.
1. Visión General
La creación de pruebas eficientes para aplicaciones de Spring es crucial para garantizar que nuestro código funcione correctamente a lo largo del tiempo. Utilizando una base de datos en memoria como H2 nos permitirá realizar pruebas rápidas y sin complicaciones. Esta entrada de blog detalla los pasos necesarios para establecer una aplicación Spring que utiliza H2 para las pruebas, creando así un entorno de desarrollo flexible.
2. Dependencias de Maven
Para el desarrollo, necesitamos las siguientes dependencias en nuestro archivo pom.xml
:
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>6.0.6</version>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-jpa</artifactId>
<version>3.1.0</version>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<version>2.1.214</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>6.5.2.Final</version>
</dependency>
Las versiones más recientes de spring-test, spring-data-jpa, h2 y hibernate-core se pueden descargar desde Maven Central.
3. Modelo de Datos y Repositorio
Comencemos creando una sencilla clase Student
que será marcada como una entidad:
@Entity
public class Student {
@Id
private long id;
private String name;
// Constructor estándar, getters, setters
}
A continuación, creamos una interfaz de repositorio basada en Spring Data JPA:
public interface StudentRepository extends JpaRepository<Student, Long> {
}
Esto permitirá que Spring genere el soporte para manipular objetos Student
.
4. Fuentes de Propiedades Separadas
Para permitir el uso de diferentes configuraciones de base de datos para el modo normal y el modo de prueba, podemos leer las propiedades de la base de datos desde un archivo cuya ubicación varía dependiendo de si la aplicación está en ejecución en modo normal o en modo de prueba.
Para el modo normal, el archivo de propiedades residirá en src/main/resources
, y para el modo de prueba, utilizaremos un archivo de propiedades en la carpeta src/test/resources
.
La aplicación primero buscará archivos en la carpeta src/test/resources
cuando se ejecute una prueba. Si el archivo no se encuentra en esta ubicación, utilizará el que esté definido en la carpeta src/main/resources
. Si el archivo está presente en la carpeta de prueba, entonces anulará al de la carpeta principal.
4.1. Definiendo los Archivos de Propiedades
Creamos un archivo persistence-student.properties
en la carpeta src/main/resources
que definirá las propiedades para una fuente de datos MySQL:
dbc.driverClassName=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/myDb
jdbc.user=tutorialuser
jdbc.pass=tutorialpass
hibernate.dialect=org.hibernate.dialect.MySQLDialect
hibernate.hbm2ddl.auto=create-drop
En la configuración anterior, necesitaremos tener la base de datos myDb
creada y el usuario tutorialuser/tutorialpass
configurado.
Como queremos utilizar una base de datos en memoria para las pruebas, crearemos un archivo similar en la carpeta src/test/resources
, que contendrá las mismas claves y valores específicos de la base de datos H2:
jdbc.driverClassName=org.h2.Driver
jdbc.url=jdbc:h2:mem:myDb;DB_CLOSE_DELAY=-1;NON_KEYWORDS=KEY,VALUE
hibernate.dialect=org.hibernate.dialect.H2Dialect
hibernate.hbm2ddl.auto=create
Hemos configurado la base de datos H2 para que funcione en memoria y se cree automáticamente, para cerrarse y eliminarse cuando la JVM termine.
4.2. Configuración de JPA
Creamos una clase @Configuration
que busque un archivo llamado persistence-student.properties
como fuente de propiedades y cree una DataSource
utilizando las propiedades de la base de datos definidas dentro.
@Configuration
@EnableJpaRepositories(basePackages = "com.baeldung.persistence.dao")
@PropertySource("persistence-student.properties")
@EnableTransactionManagement
public class StudentJpaConfig {
@Autowired
private Environment env;
@Bean
public DataSource dataSource() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName(env.getProperty("jdbc.driverClassName"));
dataSource.setUrl(env.getProperty("jdbc.url"));
dataSource.setUsername(env.getProperty("jdbc.user"));
dataSource.setPassword(env.getProperty("jdbc.pass"));
return dataSource;
}
// configurar entityManagerFactory
// configurar transactionManager
// configurar propiedades adicionales de Hibernate
}
5. Creando una Prueba JUnit
Vamos a escribir una sencilla prueba JUnit basada en la configuración mencionada anteriormente que utiliza el StudentRepository
para guardar y recuperar una entidad Student
:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(
classes = { StudentJpaConfig.class },
loader = AnnotationConfigContextLoader.class)
@Transactional
public class InMemoryDBTest {
@Resource
private StudentRepository studentRepository;
@Test
public void givenStudent_whenSave_thenGetOk() {
Student student = new Student(1, "john");
studentRepository.save(student);
Student student2 = studentRepository.findOne(1);
assertEquals("john", student2.getName());
}
}
Nuestra prueba se ejecutará de manera completamente autónoma: se creará una base de datos en memoria H2, se ejecutarán las declaraciones y luego se cerrará la conexión y se eliminará la base de datos, como se puede ver en el log:
INFO: HHH000400: Using dialect: org.hibernate.dialect.H2Dialect
Hibernate: drop table Student if exists
Hibernate: create table Student (id bigint not null, name varchar(255), primary key (id))
6. Conclusión
En este breve ejemplo, hemos mostrado cómo ejecutar una prueba autónoma utilizando una base de datos en memoria. Esta metodología simplifica el proceso de pruebas en ambientes de desarrollo, permitiendo a los programadores centrarse en la lógica de negocio sin preocuparse por la complejidad de la configuración del entorno de base de datos.
Consejos Prácticos
- Configura tus pruebas para que sean independientes: Asegúrate de que cada prueba pueda ejecutarse de manera aislada, lo que permite la paralelización y evita efectos secundarios.
- Aprovecha las bases de datos en memoria: Usa H2 u otra base de datos en memoria para pruebas rápidas y reutilizables, lo que te ayudará a acelerar el proceso de prueba.
- Mantén el entorno de prueba dentro del código: Mantén las configuraciones específicas de prueba en la carpeta
src/test/resources
para facilitar la gestión y evitar problemas en producción. - Automatiza tus pruebas: Integra tus pruebas de JUnit en un entorno de integración continua para que se ejecuten automáticamente en cada cambio del código.
Siguiendo estas pautas, podrás lograr un entorno de desarrollo y pruebas sencillo y efectivo en tus proyectos de programación en Java. ¡Feliz programación!