Eigenes Testen mit einer In-Memory-Datenbank

Eigenständiges Testen mit einer In-Memory-Datenbank

1. Überblick

In diesem Tutorial gehen wir zucreate a simple Spring application which relies on an in-memory database for testing.

Für das Standardprofil verfügt die Anwendung über eine eigenständige MySQL-Datenbankkonfiguration, für die der MySQL-Server installiert und ausgeführt werden muss und für die ein geeigneter Benutzer und eine geeignete Datenbank eingerichtet sind.

Um das Testen der Anwendung zu vereinfachen, verzichten wir auf die zusätzliche Konfiguration, die für MySQL erforderlich ist, und verwenden stattdessen eineH2 In-Memory-Datenbank zum Ausführen der JUnit-Tests.

2. Maven-Abhängigkeiten

Für die Entwicklung benötigen wir folgende Abhängigkeiten:


    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

Die neuesten Versionen vonspring-test,spring-data-jpa,h2 undhibernate-entitymanager können von Maven Central heruntergeladen werden.

3. Datenmodell und Repository

Erstellen wir eine einfacheStudent-Klasse, die als Entität markiert wird:

@Entity
public class Student {

    @Id
    private long id;

    private String name;

    // standard constructor, getters, setters
}

Als Nächstes erstellen wir eine Repository-Schnittstelle basierend auf Spring Data JPA:

public interface StudentRepository extends JpaRepository {
}

Dadurch kann Spring die Unterstützung für die Bearbeitung vonStudent-Objekten erstellen.

4. Separate Eigenschaftsquellen

Um die Verwendung unterschiedlicher Datenbankkonfigurationen für den Standardmodus und den Testmodus zu ermöglichen, können die Datenbankeigenschaften aus einer Datei gelesen werden, deren Speicherort sich je nach dem Ausführungsmodus der Anwendung unterscheidet.

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.

Wenn Sie einen Test ausführen, sucht die Anwendung zuerst nach Dateien im Ordnersrc/test/resources. Wenn die Datei nicht an diesem Speicherort gefunden wird, wird die im Ordnersrc/main/resourcesdefinierte verwendet. Wenn die Datei vorhanden ist, die den Pfad vontestenthält, überschreibt sie den Pfad aus dem Pfad vonmain.

4.1. Definieren der Eigenschaftendateien

Erstellen wir einepersistence-student.properties-Datei imsrc/main/resources-Ordner, die Eigenschaften für eine MySQL-Datenquelle definiert:

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

Im Fall der obigen Konfiguration muss die DatenbankmyDberstellt und der Benutzertutorialuser/tutorialpasseingerichtet werden.

Da wir zum Testen eine In-Memory-Datenbank verwenden möchten, erstellen wir im Ordnersrc/test/resourceseine ähnliche Datei mit demselben Namen, die Eigenschaften mit denselben Schlüsseln und datenbankspezifischen Werten vonH2enthält:

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

Wir haben dieH2-Datenbank so konfiguriert, dass sie im Arbeitsspeicher gespeichert und automatisch erstellt, dann geschlossen und gelöscht wird, wenn die JVM beendet wird.

4.2. JPA-Konfiguration

Erstellen wir eine@Configuration-Klasse, die nach einer Datei mit dem Namenpersistence-student.properties als Eigenschaftsquelle sucht und mithilfe der darin definierten Datenbankeigenschaften eineDataSource erstellt:

@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. Erstellen eines JUnit-Tests

Schreiben wir einen einfachen JUnit-Test basierend auf der oben beschriebenen Konfiguration, der dieStudentRepository verwendet, um eineStudent-Entität zu speichern und abzurufen:

@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 - Es wird eine speicherinterneH2-Datenbank erstellt, Anweisungen ausgeführt, dann die Verbindung geschlossen und die Datenbank gelöscht, wie im Protokoll zu sehen ist:

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

In diesem kurzen Beispiel haben wir gezeigt, wie wir einen eigenständigen Test mithilfe einer In-Memory-Datenbank ausführen können.

Wie immer kann der vollständige Quellcodeover on GitHub gefunden werden.