Teste autônomo usando um banco de dados na memória

Teste autônomo usando um banco de dados na memória

1. Visão geral

Neste tutorial, vamoscreate a simple Spring application which relies on an in-memory database for testing.

Para o perfil padrão, o aplicativo terá uma configuração de banco de dados MySQL independente, que exige a instalação e execução do servidor MySQL, com um usuário e banco de dados adequados.

Para tornar o teste do aplicativo mais fácil, abandonaremos a configuração adicional exigida pelo MySQL e, em vez disso, usaremos um banco de dados na memóriaH2 para executar os testes JUnit.

2. Dependências do Maven

Para o desenvolvimento, precisamos das seguintes dependências:


    org.springframework
    spring-test
    4.3.7.RELEASE


    org.springframework.data
    spring-data-jpa
    1.11.1.RELEASE


    com.h2database
    h2
    1.4.194


    org.hibernate
    hibernate-entitymanager
    5.2.9.Final

As versões mais recentes despring-test,spring-data-jpa,h2 ehibernate-entitymanager podem ser baixadas do Maven Central.

3. Modelo de dados e repositório

Vamos criar uma classeStudent simples que será marcada como uma entidade:

@Entity
public class Student {

    @Id
    private long id;

    private String name;

    // standard constructor, getters, setters
}

A seguir, vamos criar uma interface de repositório baseada em Spring Data JPA:

public interface StudentRepository extends JpaRepository {
}

Isso permitirá que o Spring crie o suporte para manipulação de objetosStudent.

4. Fontes de propriedade separadas

Para permitir o uso de diferentes configurações de banco de dados no modo padrão e no modo de teste, podemos ler as propriedades do banco de dados de um arquivo cuja localização é diferente, dependendo do modo de execução do aplicativo.

For normal mode, the properties file will reside in src/main/resources, and for the testing method, we will use a properties file in the src/test/resources folder.

Ao executar um teste, o aplicativo procurará primeiro os arquivos na pastasrc/test/resources. Se o arquivo não for encontrado neste local, será utilizado aquele definido na pastasrc/main/resources. Se o arquivo estiver presente no caminhotest, ele substituirá aquele do caminhomain.

4.1. Definindo os Arquivos de Propriedade

Vamos criar um arquivopersistence-student.properties na pastasrc/main/resources que define propriedades para uma fonte de dados 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.MySQL5Dialect
hibernate.hbm2ddl.auto=create-drop

No caso da configuração acima, precisaremos ter o banco de dadosmyDb criado e o usuáriotutorialuser/tutorialpass configurado.

Como queremos usar um banco de dados na memória para teste, criaremos um arquivo semelhante com o mesmo nome na pastasrc/test/resources, contendo propriedades com as mesmas chaves e valores específicos do banco de dadosH2:

jdbc.driverClassName=org.h2.Driver
jdbc.url=jdbc:h2:mem:myDb;DB_CLOSE_DELAY=-1

hibernate.dialect=org.hibernate.dialect.H2Dialect
hibernate.hbm2ddl.auto=create

Configuramos o banco de dadosH2 para viver na memória e ser criado automaticamente, depois fechado e descartado quando a JVM for encerrada.

4.2. Configuração JPA

Vamos criar uma classe@Configuration que procura um arquivo chamadopersistence-student.properties como uma fonte de propriedade e cria umDataSource usando as propriedades do banco de dados definidas nele:

@Configuration
@EnableJpaRepositories(basePackages = "org.example.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;
    }

    // configure entityManagerFactory

    // configure transactionManager

    // configure additional Hibernate Properties
}

5. Criação de um teste JUnit

Vamos escrever um teste JUnit simples com base na configuração descrita acima que usaStudentRepository para salvar e recuperar uma entidadeStudent:

@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());
    }
}

Our test will run in an entirely self-contained manner - criará um banco de dadosH2 na memória, executará instruções, feche a conexão e eliminará o banco de dados, como podemos ver no 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))
Mar 24, 2017 12:41:51 PM org.hibernate.tool.schema.internal.SchemaCreatorImpl applyImportSources
INFO: HHH000476: Executing import script 'org.hiber[email protected]1b8f9e2'
Hibernate: select student0_.id as id1_0_0_, student0_.name as name2_0_0_ from Student student0_ where student0_.id=?
Hibernate: drop table Student if exists

6. Conclusão

Neste exemplo rápido, mostramos como podemos executar um teste independente usando um banco de dados na memória.

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