Escribir pruebas con Testcontainers
Antes de escribir las pruebas, crea un script SQL para sembrar datos de prueba en
src/test/resources/test-data.sql:
DELETE FROM comments;
DELETE FROM posts;
DELETE FROM users;
INSERT INTO users(id, name, email) VALUES
(1, 'Siva', '[email protected]'),
(2, 'Oleg', '[email protected]');
INSERT INTO posts(id, title, content, created_by, created_at) VALUES
(1, 'Post 1 Title', 'Post 1 content', 1, CURRENT_TIMESTAMP),
(2, 'Post 2 Title', 'Post 2 content', 2, CURRENT_TIMESTAMP);
INSERT INTO comments(id, name, content, post_id, created_at) VALUES
(1, 'Ron', 'Comment 1', 1, CURRENT_TIMESTAMP),
(2, 'James', 'Comment 2', 1, CURRENT_TIMESTAMP),
(3, 'Robert', 'Comment 3', 2, CURRENT_TIMESTAMP);Probar con el slice @JooqTest
La anotación @JooqTest carga únicamente los componentes de la capa de
persistencia y autoconfigura el DSLContext de jOOQ. Utiliza la URL JDBC especial
de Testcontainers para iniciar un contenedor de Postgres.
Crea UserRepositoryJooqTest.java:
package com.testcontainers.demo.domain;
import static org.assertj.core.api.Assertions.assertThat;
import org.jooq.DSLContext;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.jooq.JooqTest;
import org.springframework.test.context.jdbc.Sql;
@JooqTest(
properties = {
"spring.test.database.replace=none",
"spring.datasource.url=jdbc:tc:postgresql:16-alpine:///db",
}
)
@Sql("/test-data.sql")
class UserRepositoryJooqTest {
@Autowired
DSLContext dsl;
UserRepository repository;
@BeforeEach
void setUp() {
this.repository = new UserRepository(dsl);
}
@Test
void shouldCreateUserSuccessfully() {
User user = new User(null, "John", "[email protected]");
User savedUser = repository.createUser(user);
assertThat(savedUser.id()).isNotNull();
assertThat(savedUser.name()).isEqualTo("John");
assertThat(savedUser.email()).isEqualTo("[email protected]");
}
@Test
void shouldGetUserByEmail() {
User user = repository.getUserByEmail("[email protected]").orElseThrow();
assertThat(user.id()).isEqualTo(1L);
assertThat(user.name()).isEqualTo("Siva");
assertThat(user.email()).isEqualTo("[email protected]");
}
}Esto es lo que hace la prueba:
@JooqTestcarga solo la capa de persistencia y autoconfiguraDSLContext.- La URL JDBC especial de Testcontainers (
jdbc:tc:postgresql:16-alpine:///db) inicia automáticamente un contenedor de PostgreSQL. - Debido a que
flyway-coreestá en el classpath, Spring Boot ejecuta las migraciones de Flyway desdesrc/main/resources/db/migrational iniciar. @Sql("/test-data.sql")carga los datos de prueba antes de cada prueba.- Se instancia manualmente
UserRepositorycon elDSLContextinyectado.
Prueba de integración con @SpringBootTest
Para una prueba de integración completa, utiliza @SpringBootTest con el soporte
@ServiceConnection de Testcontainers introducido en Spring Boot 3.1.
Crea UserRepositoryTest.java:
package com.testcontainers.demo.domain;
import static org.assertj.core.api.Assertions.assertThat;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.testcontainers.service.connection.ServiceConnection;
import org.springframework.test.context.jdbc.Sql;
import org.testcontainers.postgresql.PostgreSQLContainer;
import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers;
@SpringBootTest
@Sql("/test-data.sql")
@Testcontainers
class UserRepositoryTest {
@Container
@ServiceConnection
static PostgreSQLContainer postgres = new PostgreSQLContainer(
"postgres:16-alpine"
);
@Autowired
UserRepository repository;
@Test
void shouldCreateUserSuccessfully() {
User user = new User(null, "John", "[email protected]");
User savedUser = repository.createUser(user);
assertThat(savedUser.id()).isNotNull();
assertThat(savedUser.name()).isEqualTo("John");
assertThat(savedUser.email()).isEqualTo("[email protected]");
}
@Test
void shouldGetUserByEmail() {
User user = repository.getUserByEmail("[email protected]").orElseThrow();
assertThat(user.id()).isEqualTo(1L);
assertThat(user.name()).isEqualTo("Siva");
assertThat(user.email()).isEqualTo("[email protected]");
}
}Esto es lo que hace la prueba:
@SpringBootTestcarga todo el contexto de la aplicación, por lo queUserRepositoryse inyecta directamente.@Testcontainersy@Containergestionan el ciclo de vida del contenedor de PostgreSQL.@ServiceConnectionautoconfigura las propiedades del datasource a partir del contenedor en ejecución, eliminando la necesidad de usar@DynamicPropertySource.@Sql("/test-data.sql")inicializa los datos de prueba.
Probar PostRepository
Prueba el PostRepository que recupera grafos de objetos complejos utilizando la
URL JDBC especial de Testcontainers.
Crea PostRepositoryTest.java:
package com.testcontainers.demo.domain;
import static org.assertj.core.api.Assertions.assertThat;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.jdbc.Sql;
@SpringBootTest(
properties = {
"spring.test.database.replace=none",
"spring.datasource.url=jdbc:tc:postgresql:16-alpine:///db",
}
)
@Sql("/test-data.sql")
class PostRepositoryTest {
@Autowired
PostRepository repository;
@Test
void shouldGetPostById() {
Post post = repository.getPostById(1L).orElseThrow();
assertThat(post.id()).isEqualTo(1L);
assertThat(post.title()).isEqualTo("Post 1 Title");
assertThat(post.content()).isEqualTo("Post 1 content");
assertThat(post.createdBy().id()).isEqualTo(1L);
assertThat(post.createdBy().name()).isEqualTo("Siva");
assertThat(post.createdBy().email()).isEqualTo("[email protected]");
assertThat(post.comments()).hasSize(2);
}
}Esta prueba verifica que getPostById carga la publicación junto con su creador
y comentarios en una sola consulta utilizando la característica MULTISET de
jOOQ.