Integrationstest für Datenbankzugriffe mit automatischem Rollback in Spring

Um die Datenbank-Schicht einer Anwendung zu testen, bietet das Spring Test-Framework Transaktionen für die Test-Klassen an. Dies ermöglicht es, die Anforderung zu erfüllen dass die einzelnen Test-Methoden voneinander unabhängig sind.

Richtig konfiguriert startet Spring für jede Test-Methode eine Transaktion und setzt nach der Ausführung automatisch ein Rollback ab um die Datenbank wieder in den ursprünglichen Zustand zu versetzen. Somit können in jeder Test-Methode beliebige Testdaten erzeugt und abgefragt werden, sobald der Test beendet ist startet der nächste Test wieder unabhängig davon mit der Datenbank im Ausgangszustand und die Reihenfolge der Test-Ausführungen ist irrelevant.

Um dies zu ermöglichen, muss die Test-Klasse nur mit 2 speziellen Annotationen gekennzeichnet werden. Hier ein Beispiel:

package at.myproject;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;

import javax.transaction.Transactional;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.TestExecutionListeners;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.support.DependencyInjectionTestExecutionListener;
import org.springframework.test.context.transaction.TransactionalTestExecutionListener;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"classpath:test-app-context.xml"})
@TestExecutionListeners({ DependencyInjectionTestExecutionListener.class, TransactionalTestExecutionListener.class })
@Transactional
public class MyDbTest {

    @Autowired
    EmployeeDAO employeeDAO;

    @Test
    public void testMethod1() {
         // .... doing some tests, rollback is automatically executed after test 
    }

    @Test
    public void testMethod2() {
         // .... doing some tests, rollback is automatically executed after test
    }

}

Zuerst geben wir mit @RunWith an, dass der Test mit der Spring-eigenen Runner-Klasse für JUnit ausgeführt werden soll. Mit @ContextConfiguration setzen wir die Test-Konfiguration auf, in welcher wir auch den Zugriff zur Test-Datenbank konfigurieren.

Die @TestExecutionListeners-Annotation startet einerseits die Dependency-Injection (da wir hier @Autowired verwenden) und gibt mittels des TransactionalTestExecutionListener an dass Spring die Test-Methoden innnerhalb einer Transaktion ausführen kann. Dies muss dann mit @Transactional noch eingeschalten werden.

Damit ist alles konfiguriert und wir müssen uns um ein Rollback nicht mehr explizit kümmern.

Möchte man aus welchem Grund auch immer doch ein Commit anstatt eines Rollbacks absenden, kann man die Test-Methode mit einer @Commit-Annotation versehen.

Schreibe einen Kommentar