Testes de Integração de Repositório: Configuração

Ao finalizarmos esta aula, seremos capazes de:

  • Iniciar e encerrar um contêiner Docker que executa um banco de dados PostgreSQL.
  • Compreender como podemos eliminar código de configuração duplicado ao configurar nossos testes de integração.

Esta aula assume que:

  • Você está familiarizado com o DbUnit (ou com o gerenciamento de estado de banco de dados via @DatabaseSetup / @Sql)
  • Você sabe configurar seus testes de integração no ecossistema Spring
  • Você está familiarizado com o JUnit Jupiter (JUnit 5 / JUnit 6.0.3)
  • Você está familiarizado com o Testcontainers (2.0.5)
  • Você sabe integrar o Testcontainers com o JUnit Jupiter
  • Você sabe escrever testes de integração com JUnit Jupiter e Testcontainers
  • Você sabe executar testes em Kotlin (2.4.21) com Maven ou Gradle (9.8.2 Kotlin DSL).

Configurando Nossa Conexão com o Banco de Dados

Antes de podermos configurar nossos testes de integração, precisamos garantir que o Testcontainers inicie um banco de dados PostgreSQL antes que nossos testes de integração sejam executados. Podemos fazer isso seguindo estes passos:

Primeiro, precisamos garantir que o nosso classpath contenha tanto o Testcontainers quanto o driver JDBC do PostgreSQL (por exemplo, no build.gradle.kts com Gradle 9.8.2 Kotlin DSL, utilizando org.testcontainers:postgresql:2.0.5, org.testcontainers:jdbc:2.0.5 e org.postgresql:postgresql).

Se você não sabe como adicionar essas dependências ao seu classpath, consulte a aula de introdução ao Testcontainers.

Segundo, precisamos configurar nossa conexão com o banco de dados fazendo as seguintes alterações em nosso arquivo de propriedades (application-integrationTest.properties):

  1. Configurar a URL JDBC utilizando o seguinte formato: jdbc:tc:postgresql:[versão do banco de dados]://[host]:[porta]/[nome do banco de dados].
  2. Garantir que nossa aplicação Spring Boot (4.1.2) utilize o driver JDBC fornecido pelo Testcontainers (org.testcontainers.jdbc.ContainerDatabaseDriver).

Depois de configurarmos nossa conexão com o banco de dados, o arquivo application-integrationTest.properties fica com a seguinte aparência:

1
2
3
4
5
6
7
8
9
spring.datasource.type=com.zaxxer.hikari.HikariDataSource
spring.datasource.url=jdbc:tc:postgresql:17-alpine:///integrationTest
spring.datasource.driver-class-name=org.testcontainers.jdbc.ContainerDatabaseDriver

#I18N
spring.messages.basename=i18n/messages

#Liquibase Configuration
spring.liquibase.change-log=classpath:/db/changelog/db.changelog.xml

Nota sobre versões da imagem PostgreSQL: No projeto original de 2020 utilizava-se jdbc:tc:postgresql:12.1:///integrationTest. Na stack moderna com Testcontainers 2.0.5 e Spring Boot 4.1.2, o funcionamento da URL mágica jdbc:tc: permanece idêntico, podendo-se especificar imagens atuais como 17-alpine ou 12.1 conforme a necessidade do seu ambiente.

A seguir, aprenderemos a configurar nossos testes de integração.

Configurando Nossos Testes de Integração

Podemos configurar nossos testes de integração seguindo estes passos:

Primeiro, como queremos eliminar código de configuração duplicado de nossos testes de integração, precisamos criar uma anotação customizada que contenha a configuração compartilhada pelos nossos testes de integração. Podemos criar essa anotação seguindo estes passos:

  1. Criar uma nova classe de anotação (annotation class).
  2. Garantir que nossa anotação customizada possa ser aplicada a uma classe de teste (@Target(AnnotationTarget.CLASS)).
  3. Garantir que nossa anotação customizada seja armazenada na saída binária e fique visível para reflexão em tempo de execução (@Retention(AnnotationRetention.RUNTIME)).
  4. Garantir que nossa anotação customizada seja incluída na documentação gerada a partir de nossas classes de teste (@MustBeDocumented).
  5. Garantir que nossos testes de integração carreguem o contexto de aplicação (ApplicationContext) da nossa aplicação Spring Boot e habilitem as melhorias de teste fornecidas pelo Spring Boot (@SpringBootTest).
  6. Integrar o DbUnit com o framework Spring TestContext (@TestExecutionListeners).
  7. Configurar o perfil ativo do Spring. Observe que nossos testes de integração devem usar um perfil do Spring chamado: integrationTest (@ActiveProfiles("integrationTest")).
  8. Marcar nossa classe de teste como uma classe de teste de integração usando a tag do JUnit Jupiter: integrationTest (@Tag("integrationTest")).

Depois de criarmos a anotação @DatabaseIntegrationTest, seu código-fonte em Kotlin fica da seguinte forma:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
import com.github.springtestdbunit.DbUnitTestExecutionListener
import org.junit.jupiter.api.Tag
import org.junit.jupiter.api.extension.ExtendWith
import org.springframework.boot.test.context.SpringBootTest
import org.springframework.test.context.ActiveProfiles
import org.springframework.test.context.ContextConfiguration
import org.springframework.test.context.TestExecutionListeners
import org.springframework.test.context.junit.jupiter.SpringExtension

@Target(AnnotationTarget.CLASS)
@Retention(AnnotationRetention.RUNTIME)
@MustBeDocumented
@SpringBootTest
@TestExecutionListeners(
    listeners = [DbUnitTestExecutionListener::class],
    mergeMode = TestExecutionListeners.MergeMode.MERGE_WITH_DEFAULTS
)
@ActiveProfiles("integrationTest")
@Tag("integrationTest")
annotation class DatabaseIntegrationTest

Segundo, quando criarmos uma nova classe de teste que contenha testes de integração para um repositório (seja com jOOQ ou Spring Data), devemos anotar a classe de teste com a anotação @DatabaseIntegrationTest.

Depois de fazermos isso, o código-fonte da nossa classe de teste fica da seguinte forma:

1
2
3
@DatabaseIntegrationTest
class RepositoryTest {
}

Agora podemos iniciar o banco de dados PostgreSQL antes que nossos testes de integração sejam executados, e sabemos como configurar nossos testes de integração sem escrever nenhum código duplicado. Vamos resumir o que aprendemos nesta aula.

Resumo

Esta aula nos ensinou duas coisas:

  • Se quisermos que o Testcontainers inicie um banco de dados PostgreSQL antes que nossos testes de integração sejam executados, devemos usar o driver JDBC fornecido pelo Testcontainers (org.testcontainers.jdbc.ContainerDatabaseDriver) e configurar a URL do nosso data source usando um formato especial (jdbc:tc:postgresql:...).
  • Como queremos configurar nossos testes de integração sem escrever código de configuração duplicado, devemos criar uma anotação customizada (@DatabaseIntegrationTest) que contenha a configuração compartilhada pelos nossos testes de integração.