Test autonome en utilisant une base de données en mémoire

Test autonome en utilisant une base de données en mémoire

1. Vue d'ensemble

Dans ce didacticiel, nous allons àcreate a simple Spring application which relies on an in-memory database for testing.

Pour le profil standard, l'application disposera d'une configuration de base de données MySQL autonome, qui nécessite l'installation et le fonctionnement du serveur MySQL, avec un utilisateur et une base de données appropriés.

Pour faciliter le test de l'application, nous renoncerons à la configuration supplémentaire requise par MySQL et utiliserons à la place une base de données en mémoireH2 pour exécuter les tests JUnit.

2. Dépendances Maven

Pour le développement, nous avons besoin des dépendances suivantes:


    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

Les dernières versions despring-test,spring-data-jpa,h2 ethibernate-entitymanager peuvent être téléchargées depuis Maven Central.

3. Modèle de données et référentiel

Créons une simple classeStudent qui sera marquée comme une entité:

@Entity
public class Student {

    @Id
    private long id;

    private String name;

    // standard constructor, getters, setters
}

Ensuite, créons une interface de référentiel basée sur Spring Data JPA:

public interface StudentRepository extends JpaRepository {
}

Cela permettra à Spring de créer le support pour la manipulation des objetsStudent.

4. Sources de propriété distinctes

Pour permettre l'utilisation de différentes configurations de base de données pour le mode standard et le mode test, nous pouvons lire les propriétés de la base de données à partir d'un fichier dont l'emplacement est différent selon le mode d'exécution de l'application.

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.

Lors de l'exécution d'un test, l'application recherchera d'abord les fichiers dans le dossiersrc/test/resources. Si le fichier n'est pas trouvé à cet emplacement, il utilisera celui défini dans le dossiersrc/main/resources. Si le fichier est présent dans le chemin detest, alors il remplacera celui du chemin demain.

4.1. Définition des fichiers de propriétés

Créons un fichierpersistence-student.properties dans le dossiersrc/main/resources qui définit les propriétés d’une source de données 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

Dans le cas de la configuration ci-dessus, nous aurons besoin d'avoir la base de donnéesmyDb créée et l'utilisateur detutorialuser/tutorialpass configuré.

Puisque nous voulons utiliser une base de données en mémoire pour les tests, nous allons créer un fichier similaire avec le même nom dans le dossiersrc/test/resources, contenant les propriétés avec les mêmes clés et les valeurs spécifiques à la base de donnéesH2:

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

Nous avons configuré la base de donnéesH2 pour qu'elle vive en mémoire et qu'elle soit créée automatiquement, puis fermée et supprimée lorsque la JVM se termine.

4.2. Configuration JPA

Créons une classe@Configuration qui recherche un fichier appelépersistence-student.properties comme source de propriété et crée unDataSource à l’aide des propriétés de base de données qui y sont définies:

@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. Création d'un test JUnit

Écrivons un test JUnit simple basé sur la configuration décrite ci-dessus qui utilise lesStudentRepository pour enregistrer et récupérer une entitéStudent:

@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 - il créera une base de donnéesH2 en mémoire, exécutera des instructions, puis fermera la connexion et supprimera la base de données, comme nous pouvons le voir dans le journal:

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. Conclusion

Dans cet exemple rapide, nous avons montré comment nous pouvons exécuter un test autonome à l'aide d'une base de données en mémoire.

Comme toujours, le code source complet peut être trouvéover on GitHub.