Saltar al contenido

Postgres integrado para pruebas de Spring Boot

Nuestro grupo redactor ha pasado mucho tiempo investigando la respuesta a tus búsquedas, te dejamos la solución por esto nuestro objetivo es que sea de mucha ayuda.

Solución:

Soy el autor de la biblioteca embedded-database-spring-test que fue mencionada por @MartinVolejnik. Creo que la biblioteca debería satisfacer todas sus necesidades (PostgreSQL + Spring Boot + Flyway + pruebas de integración). Lamento mucho que tengas problemas, así que he creado una aplicación de demostración simple que demuestra el uso de la biblioteca junto con el marco Spring Boot. A continuación, he resumido los pasos básicos que debe seguir.

Configuración de Maven

Agregue la siguiente dependencia de maven:


    io.zonky.test
    embedded-database-spring-test
    1.5.2
    test

Configuración de la vía migratoria

Agregue la siguiente propiedad a la configuración de su aplicación:

# Sets the schemas managed by Flyway -> change the xxx value to the name of your schema
# flyway.schemas=xxx // for spring boot 1.x.x
spring.flyway.schemas=xxx // for spring boot 2.x.x

Además, asegúrese de no utilizar org.flywaydb.test.junit.FlywayTestExecutionListener. Debido a que la biblioteca tiene su propio oyente de ejecución de prueba que puede optimizar la inicialización de la base de datos y esta optimización no tiene ningún efecto si el FlywayTestExecutionListener Está aplicado.

Configuración de Spring Boot 2

Desde Spring Boot 2, existe un problema de compatibilidad con Hibernate y Postgres Driver. Por lo tanto, es posible que deba agregar la siguiente propiedad a la configuración de su aplicación para solucionarlo:

# Workaround for a compatibility issue of Spring Boot 2 with Hibernate and Postgres Driver
# See https://github.com/spring-projects/spring-boot/issues/12007
spring.jpa.properties.hibernate.jdbc.lob.non_contextual_creation=true

Ejemplo

Un ejemplo de clase de prueba que demuestra el uso de la base de datos integrada:

@RunWith(SpringRunner.class)
@DataJpaTest
@AutoConfigureEmbeddedDatabase
public class SpringDataJpaAnnotationTest 

    @Autowired
    private PersonRepository personRepository;

    @Test
    public void testEmbeddedDatabase() 
        Optional personOptional = personRepository.findById(1L);

        assertThat(personOptional).hasValueSatisfying(person -> 
            assertThat(person.getId()).isNotNull();
            assertThat(person.getFirstName()).isEqualTo("Dave");
            assertThat(person.getLastName()).isEqualTo("Syer");
        );
    

La siguiente configuración funciona bien con Spring Boot 2.0.

La ventaja sobre la prueba de primavera de la base de datos incrustada es que esta solución no empuja a Flyway a la ruta de clase, posiblemente arruinando la configuración automática de Spring Boot.

@Configuration
@Slf4j
public class EmbeddedPostgresConfiguration 

    @Bean(destroyMethod = "stop")
    public PostgresProcess postgresProcess() throws IOException 
        log.info("Starting embedded Postgres");

        String tempDir = System.getProperty("java.io.tmpdir");
        String dataDir = tempDir + "/database_for_tests";
        String binariesDir = System.getProperty("java.io.tmpdir") + "/postgres_binaries";

        PostgresConfig postgresConfig = new PostgresConfig(
                Version.V10_3,
                new AbstractPostgresConfig.Net("localhost", Network.getFreeServerPort()),
                new AbstractPostgresConfig.Storage("database_for_tests", dataDir),
                new AbstractPostgresConfig.Timeout(60_000),
                new AbstractPostgresConfig.Credentials("bob", "ninja")
        );

        PostgresStarter runtime =
                PostgresStarter.getInstance(EmbeddedPostgres.cachedRuntimeConfig(Paths.get(binariesDir)));
        PostgresExecutable exec = runtime.prepare(postgresConfig);
        PostgresProcess process = exec.start();

        return process;
    

    @Bean(destroyMethod = "close")
    @DependsOn("postgresProcess")
    DataSource dataSource(PostgresProcess postgresProcess) 
        PostgresConfig postgresConfig = postgresProcess.getConfig();

        val config = new HikariConfig();
        config.setUsername(postgresConfig.credentials().username());
        config.setPassword(postgresConfig.credentials().password());
        config.setJdbcUrl("jdbc:postgresql://localhost:" + postgresConfig.net().port() + "/" + postgresConfig.storage().dbName());

        return new HikariDataSource(config);
    

Maven:

        
            ru.yandex.qatools.embed
            postgresql-embedded
            2.9
            test
        
        
            org.postgresql
            postgresql
        

La clase se basa en el código que encontré aquí: https://github.com/nkoder/postgresql-embedded-example

Lo modifiqué para usar HikariDatasource (Valor predeterminado de Spring Boot) para una agrupación de conexiones adecuada. los binariesDir y dataDir se utilizan para evitar la costosa extracción + initdb en pruebas repetidas.

Otra solución bastante limpia a ese problema es utilizar el TestContainers Biblioteca. La única advertencia es que requiere Docker.

Examen de integración:

@RunWith(SpringRunner.class)
@SpringBootTest
@ContextConfiguration(initializers = ApplicationTestsIT.Initializer.class)
public class ApplicationTestsIT {

    private static int POSTGRES_PORT = 5432;

    @Autowired
    private FooRepository fooRepository;

    @ClassRule
    public static PostgreSQLContainer postgres = new PostgreSQLContainer<>("postgres")
            .withDatabaseName("foo")
            .withUsername("it_user")
            .withPassword("it_pass")
            .withInitScript("sql/init_postgres.sql");

    static class Initializer implements ApplicationContextInitializer 
        public void initialize(ConfigurableApplicationContext configurableApplicationContext) 
            TestPropertyValues.of(
                    "spring.data.postgres.host=" + postgres.getContainerIpAddress(),
                    "spring.data.postgres.port=" + postgres.getMappedPort(POSTGRES_PORT),
                    "spring.data.postgres.username=" + postgres.getUsername(),
                    "spring.data.postgres.password=" + postgres.getPassword()
            ).applyTo(configurableApplicationContext.getEnvironment());
        
    

    @Test
    public void fooRepositoryTestIT() 
        ...
    

Configuración de dependencia:
pom.xml:


    org.testcontainers
    postgresql
    test

build.gradle:

testCompile "org.testcontainers:postgresql:x.x.x"

Enlaces:

TestContainers – Bases de datos
TestContainers – Módulo Postgres

Puedes añadir valor a nuestro contenido informacional añadiendo tu experiencia en las interpretaciones.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *