Configurando o DataSource separado da Spring para testes

Configurando o DataSource separado da Spring para testes

1. Visão geral

Ao testar um aplicativo Spring que depende de uma camada de persistência, como a JPA, talvez desejemos configurar uma fonte de dados de teste para usar um banco de dados menor e mais rápido - diferente do que usamos para executar o aplicativo - para para facilitar a execução de nossos testes.

Configurar uma fonte de dados no Spring requer a definição de um bean do tipoDataSource, manualmente ou, se estiver usando Spring Boot, por meio de propriedades padrão do aplicativo.

Neste tutorial rápido, vamos dar uma olhada emseveral ways to configure a separate data source for testing in Spring.

2. Dependências do Maven

Vamos criar um aplicativo Spring Boot usando o Spring JPA e o teste, portanto, precisaremos das seguintes dependências:


    org.springframework.boot
    spring-boot-starter-data-jpa
    2.1.3.RELEASE


    com.h2database
    h2
    1.4.197


    org.springframework.boot
    spring-boot-starter-test
    2.1.3.RELEASE

As versões mais recentes despring-boot-starter-data-jpa,h2espring-boot-starter-test podem ser baixadas do Maven Central.

Vamos dar uma olhada em algumas maneiras diferentes de configurar umDataSource para teste.

3. Usando um arquivo de propriedades padrão no Spring Boot

O arquivo de propriedades padrão que Spring Boot pega automaticamente ao executar um aplicativo é chamadoapplication.propertiese reside na pastasrc/main/resources.

Se quisermos usar propriedades diferentes para os testes, podemos substituir o arquivo de propriedades na pastamain, colocando outro arquivo com o mesmo nome emsrc/test/resources.

O arquivoapplication.properties na pastasrc/test/resources deve conter os pares de valores-chave padrão necessários para configurar uma fonte de dados. Essas propriedades são prefixadas comspring.datasource.

Por exemplo, vamos configurar um banco de dados na memóriaH2 como uma fonte de dados para testes:

spring.datasource.driver-class-name=org.h2.Driver
spring.datasource.url=jdbc:h2:mem:db;DB_CLOSE_DELAY=-1
spring.datasource.username=sa
spring.datasource.password=sa

Spring Boot usará essas propriedades para configurar automaticamente um beanDataSource.

Vamos definir umGenericEntitye repositório muito simples usando Spring JPA:

@Entity
public class GenericEntity {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;
    private String value;

    //standard constructors, getters, setters
}
public interface GenericEntityRepository
  extends JpaRepository { }

A seguir, vamos escrever um testeJUnit para o repositório. Para que um teste em um aplicativo Spring Boot pegue as propriedades da fonte de dados padrão que definimos, ele deve ser anotado com@SpringBootTest:

@RunWith(SpringRunner.class)
@SpringBootTest(classes = Application.class)
public class SpringBootJPAIntegrationTest {

    @Autowired
    private GenericEntityRepository genericEntityRepository;

    @Test
    public void givenGenericEntityRepository_whenSaveAndRetreiveEntity_thenOK() {
        GenericEntity genericEntity = genericEntityRepository
          .save(new GenericEntity("test"));
        GenericEntity foundEntity = genericEntityRepository
          .findOne(genericEntity.getId());

        assertNotNull(foundEntity);
        assertEquals(genericEntity.getValue(), foundEntity.getValue());
    }
}

4. Usando um arquivo de propriedades personalizadas

Se não quisermos usar o arquivo e as chavesapplication.properties padrão, ou se não estivermos usando Spring Boot, podemos definir um arquivo.properties personalizado com chaves personalizadas e, em seguida, ler este arquivo em um Classe@Configuration para criar um beanDataSource com base nos valores que ele contém.

Este arquivo será colocado na pastasrc/main/resources para o modo de execução normal do aplicativo, e emsrc/test/resources para ser selecionado pelos testes.

Vamos criar um arquivo chamadopersistence-generic-entity.properties que usa um banco de dados de memóriaH2 para testes e colocá-lo na pastasrc/test/resources:

jdbc.driverClassName=org.h2.Driver
jdbc.url=jdbc:h2:mem:db;DB_CLOSE_DELAY=-1
jdbc.username=sa
jdbc.password=sa

Em seguida, podemos definir o beanDataSource com base nessas propriedades em uma classe@Configuration que carrega nossopersistence-generic-entity.properties como uma fonte de propriedade:

@Configuration
@EnableJpaRepositories(basePackages = "org.example.repository")
@PropertySource("persistence-generic-entity.properties")
@EnableTransactionManagement
public class H2JpaConfig {
    // ...
}

Para um exemplo mais detalhado dessa configuração, dê uma olhada em nosso artigo anterior emSelf-contained testing with an in-memory database, seção “Configuração JPA”.

Então, podemos criar um testeJUnit semelhante ao anterior, exceto que carregará nossa classe de configuração:

@RunWith(SpringRunner.class)
@SpringBootTest(classes = {Application.class, H2JpaConfig.class})
public class SpringBootH2IntegrationTest {
    // ...
}

5. Usando perfis do Spring

Outra maneira de configurar umDataSource separado para teste é aproveitando os Perfis do Spring para definir um beanDataSource que está disponível apenas em um perfiltest.

Para isso, podemos usar um arquivo.properties como antes, ou podemos escrever os valores na própria classe.

Vamos definir um beanDataSource para o perfiltest em uma classe@Configuration que será carregada por nosso teste:

@Configuration
@EnableJpaRepositories(basePackages = {
  "org.example.repository",
  "org.example.boot.repository"
})
@EnableTransactionManagement
public class H2TestProfileJPAConfig {

    @Bean
    @Profile("test")
    public DataSource dataSource() {
        DriverManagerDataSource dataSource = new DriverManagerDataSource();
        dataSource.setDriverClassName("org.h2.Driver");
        dataSource.setUrl("jdbc:h2:mem:db;DB_CLOSE_DELAY=-1");
        dataSource.setUsername("sa");
        dataSource.setPassword("sa");

        return dataSource;
    }

    // configure entityManagerFactory
    // configure transactionManager
    // configure additional Hibernate properties
}

Então, na classe de testeJUnit, precisamos especificar que queremos usar o perfiltest adicionando a anotação@ActiveProfiles:

@RunWith(SpringRunner.class)
@SpringBootTest(classes = {
  Application.class,
  H2TestProfileJPAConfig.class})
@ActiveProfiles("test")
public class SpringBootProfileIntegrationTest {
    // ...
}

6. Conclusão

Neste tutorial rápido, vimos várias maneiras em que podemos configurar umDataSource separado para teste no Spring.

Como sempre, o código-fonte completo dos exemplos pode ser encontradoover on GitHub.