Basis in Erinnerung und Testen
Und jetzt das Interessanteste. Beim Testen von Hibernate-Code möchte man sehr oft nicht mit einer echten Basis arbeiten, sondern mit einer Art Stub, der minimale Funktionalität implementiert.
Können Sie sich einen Stub vorstellen, der den Großteil des SQL Server-Standards implementiert? Ich nicht. Allerdings sind In-Memory-Datenbanken als solche hervorragend. Das funktioniert ungefähr so:
- In der @BeforeAll-Methode initialisieren wir die In-Memory-Datenbankverbindung.
- In der @BeforeEach-Methode rufen wir die Sitzung ab und öffnen eine Transaktion.
- In der @Test-Methode arbeiten wir mit der aktuellen Sitzung und Transaktion.
- In der @AfterEach-Methode schreiben wir die Transaktion fest.
- Und schließlich schließen wir in der AfterAll-Methode die Verbindung zur Datenbank.
So sieht die Prüfungsvorbereitung aus:
@Test
public class HelloTest {
private static SessionFactory sessionFactory = null;
private Session session = null;
@BeforeAll
static void setup(){
try {
StandardServiceRegistry standardRegistry = new StandardServiceRegistryBuilder()
.configure("hibernate-test.cfg.xml").build();
Metadata metadata = new MetadataSources(standardRegistry)
.addAnnotatedClass(Employee.class)
.getMetadataBuilder()
.build();
sessionFactory = metadata.getSessionFactoryBuilder().build();
} catch (Throwable ex) {
throw new ExceptionInInitializerError(ex);
}
}
@BeforeEach
void setupThis(){
session = sessionFactory.openSession();
session.beginTransaction();
}
@AfterEach
void tearThis(){
session.getTransaction().commit();
}
@AfterAll
static void tear(){
sessionFactory.close();
}
Und so sieht der Test selbst mit der Arbeit von Hibernate aus:
@Test
public class HelloTest {
@Test
void createSessionFactoryWithXML() {
Employee emp = new Employee();
emp.setEmail("demo-user@mail.com");
emp.setFirstName("demo");
emp.setLastName("user");
Assertions.assertNull(emp.getEmployeeId());
session.persist(emp);
Assertions.assertNotNull(emp.getEmployeeId());
}
}
Testdaten
Sie können Ihre Testdatenbank auch mit Testdaten füllen.
Normalerweise werden hierfür zwei SQL-Dateien erstellt:
- schema.sql enthält ein Skript, das Tabellen in der Datenbank erstellt
- test-data.sql enthält ein Skript, das Tabellen mit Testdaten füllt
Tabellenerstellung und Testdaten werden normalerweise in verschiedene Dateien aufgeteilt, da fast immer eigene Gruppen von Testdaten für verschiedene Testgruppen angezeigt werden.
Das Ausführen dieser Dateien sieht folgendermaßen aus:
void runSqlScriptFile(String filePath){
String sqlScript = new String( Files.readAllBytes(Paths.get(filePath)) );
Session session = sessionFactory.openSession();
Query query = session.createNativeQuery("BEGIN " + sqlScript + " END;");
query.executeUpdate()
}
Und Ihre Einrichtungsmethode wird sich ein wenig ändern:
@BeforeAll
static void setup(){
try {
StandardServiceRegistry standardRegistry = new StandardServiceRegistryBuilder()
.configure("hibernate-test.cfg.xml").build();
Metadata metadata = new MetadataSources(standardRegistry)
.addAnnotatedClass(Employee.class)
.getMetadataBuilder()
.build();
sessionFactory = metadata.getSessionFactoryBuilder().build();
runSqlScriptFile(“scema.sql”);
runSqlScriptFile(“test-data.sql”);
} catch (Throwable ex) {
throw new ExceptionInInitializerError(ex);
}
}