Spring Boot Integrationstest mit Embedded MongoDB

1. Übersicht

In diesem Tutorial erfahren Sie, wie Sie die eingebettete MongoDB-Lösung von Flapdoodle zusammen mit Spring Boot verwenden, um MongoDB-Integrationstests reibungslos auszuführen.

MongoDB ist eine beliebte NoSQL-Dokumentendatenbank . Dank der hohen Skalierbarkeit, integrierte in sharding und ausgezeichnete Unterstützung der Gemeinschaft es oft „betrachtet die NoSQL - Speicher“ von vielen Entwicklern.

Wie bei jeder anderen Persistenztechnologie ist es wichtig, die Datenbankintegration mit dem Rest unserer Anwendung problemlos testen zu können . Zum Glück können wir mit Spring Boot diese Art von Tests einfach schreiben.

2. Maven-Abhängigkeiten

Lassen Sie uns zunächst das übergeordnete Maven-Element für unser Boot-Projekt einrichten.

Dank des übergeordneten Elements müssen wir die Version nicht für jede Maven-Abhängigkeit manuell definieren .

Wir werden natürlich Spring Boot verwenden:

 org.springframework.boot spring-boot-starter-parent 2.3.3.RELEASE   

Die neueste Boot-Version finden Sie hier.

Da wir Spring Boot Parent hinzugefügt haben, können wir erforderliche Abhängigkeiten hinzufügen, ohne deren Versionen anzugeben:

 org.springframework.boot spring-boot-starter-data-mongodb 

Spring-Boot-Starter-Data-Mongodb aktiviert die Spring-Unterstützung für MongoDB:

 de.flapdoodle.embed de.flapdoodle.embed.mongo test 

de.flapdoodle.embed.mongo bietet eingebettete MongoDB für Integrationstests.

3. Testen Sie mit Embedded MongoDB

Dieser Abschnitt behandelt zwei Szenarien: Spring Boot-Test und manueller Test.

3.1. Spring Boot Test

Nach dem Hinzufügen der Abhängigkeit de.flapdoodle.embed.mongo versucht Spring Boot automatisch, die eingebettete MongoDB herunterzuladen und zu starten, wenn Tests ausgeführt werden.

Das Paket wird für jede Version nur einmal heruntergeladen, sodass nachfolgende Tests viel schneller ausgeführt werden.

Zu diesem Zeitpunkt sollten wir in der Lage sein, den Beispiel-Integrationstest für JUnit 5 zu starten und zu bestehen:

@DataMongoTest @ExtendWith(SpringExtension.class) public class MongoDbSpringIntegrationTest { @DisplayName("given object to save" + " when save object using MongoDB template" + " then object is saved") @Test public void test(@Autowired MongoTemplate mongoTemplate) { // given DBObject objectToSave = BasicDBObjectBuilder.start() .add("key", "value") .get(); // when mongoTemplate.save(objectToSave, "collection"); // then assertThat(mongoTemplate.findAll(DBObject.class, "collection")).extracting("key") .containsOnly("value"); } }

Wie wir sehen können, wurde die eingebettete Datenbank automatisch von Spring gestartet, das auch in der Konsole protokolliert werden sollte:

...Starting MongodbExampleApplicationTests on arroyo with PID 10413...

3.2. Manueller Konfigurationstest

Spring Boot startet und konfiguriert die eingebettete Datenbank automatisch und injiziert dann die MongoTemplate- Instanz für uns. Aber manchmal müssen wir vielleicht manuell eingebettete Mongo Datenbank konfigurieren (zB wenn eine bestimmte DB - Version zu testen).

Das folgende Snippet zeigt, wie wir die eingebettete MongoDB-Instanz manuell konfigurieren können. Dies entspricht in etwa dem vorherigen Frühlingstest:

class ManualEmbeddedMongoDbIntegrationTest { private static final String CONNECTION_STRING = "mongodb://%s:%d"; private MongodExecutable mongodExecutable; private MongoTemplate mongoTemplate; @AfterEach void clean() { mongodExecutable.stop(); } @BeforeEach void setup() throws Exception { String ip = "localhost"; int port = 27017; IMongodConfig mongodConfig = new MongodConfigBuilder().version(Version.Main.PRODUCTION) .net(new Net(ip, port, Network.localhostIsIPv6())) .build(); MongodStarter starter = MongodStarter.getDefaultInstance(); mongodExecutable = starter.prepare(mongodConfig); mongodExecutable.start(); mongoTemplate = new MongoTemplate(MongoClients.create(String.format(CONNECTION_STRING, ip, port)), "test"); } @DisplayName("given object to save" + " when save object using MongoDB template" + " then object is saved") @Test void test() throws Exception { // given DBObject objectToSave = BasicDBObjectBuilder.start() .add("key", "value") .get(); // when mongoTemplate.save(objectToSave, "collection"); // then assertThat(mongoTemplate.findAll(DBObject.class, "collection")).extracting("key") .containsOnly("value"); } }

Beachten Sie, dass wir schnell eine MongoTemplate- Bean erstellen können , die für die Verwendung unserer manuell konfigurierten eingebetteten Datenbank konfiguriert ist, und sie im Spring-Container registrieren können, indem wir lediglich eine @ TestConfiguration mit der @ Bean- Methode erstellen, die eine neue MongoTemplate (MongoClients.create (connectionString, “zurückgibt). Test ”) .

Weitere Beispiele finden Sie im offiziellen GitHub-Repository von Flapdoodle.

3.3. Protokollierung

Wir können Protokollierungsnachrichten für MongoDB konfigurieren, wenn Integrationstests ausgeführt werden, indem wir diese beiden Eigenschaften zur Datei src / test / resources / application.propertes hinzufügen :

logging.level.org.springframework.boot.autoconfigure.mongo.embedded logging.level.org.mongodb

Um beispielsweise die Protokollierung zu deaktivieren, setzen wir die Werte einfach auf Aus :

logging.level.org.springframework.boot.autoconfigure.mongo.embedded=off logging.level.org.mongodb=off

3.4. Verwenden einer realen Datenbank in der Produktion

Da wir die Abhängigkeit de.flapdoodle.embed.mongo mithilfe von test hinzugefügt haben, muss die eingebettete Datenbank nicht deaktiviert werden, wenn sie in der Produktion ausgeführt wird . Wir müssen lediglich die MongoDB-Verbindungsdetails (z. B. Host und Port) angeben und können loslegen.

Um eine eingebettete Datenbank außerhalb von Tests zu verwenden, können wir Spring-Profile verwenden, die je nach aktivem Profil den richtigen MongoClient (eingebettet oder Produktion) registrieren .

Wir müssen auch den Umfang der Produktionsabhängigkeit auf Laufzeit ändern .

4. Kontroverse um eingebettete Tests

Die Verwendung einer eingebetteten Datenbank könnte am Anfang eine gute Idee sein. In der Tat ist es ein guter Ansatz, wenn wir testen möchten, ob sich unsere Anwendung in folgenden Bereichen korrekt verhält:

  • ObjectDocument-Zuordnungskonfiguration
  • Benutzerdefinierte Listener für Persistenzlebenszyklusereignisse (siehe AbstractMongoEventListener )
  • Die Logik eines Codes, der direkt mit der Persistenzschicht arbeitet

Leider kann die Verwendung eines eingebetteten Servers nicht als "vollständiger Integrationstest" betrachtet werden . Flapdoodles eingebettete MongoDB ist kein offizielles MongoDB-Produkt. Daher können wir nicht sicher sein, dass es sich genau wie in der Produktionsumgebung verhält.

Wenn wir Kommunikationstests in der Umgebung so nah wie möglich an der Produktion durchführen möchten, ist die Verwendung eines Umgebungscontainers wie Docker eine bessere Lösung.

Um mehr über Docker zu erfahren, lesen Sie unseren vorherigen Artikel hier.

5. Schlussfolgerung

Spring Boot macht es extrem einfach, Tests auszuführen, die die ordnungsgemäße Dokumentzuordnung und Datenbankintegration überprüfen. Durch Hinzufügen der richtigen Maven-Abhängigkeit können wir MongoDB-Komponenten sofort in Spring Boot-Integrationstests verwenden.

Wir müssen uns daran erinnern, dass eingebettete MongoDB-Server nicht als Ersatz für einen „echten“ Server angesehen werden können .

Der vollständige Quellcode aller Beispiele ist auf GitHub verfügbar.