Spring Boot Integration Testing con MongoDB incorporato

1. Panoramica

In questo tutorial, impareremo come utilizzare la soluzione MongoDB incorporata di Flapdoodle insieme a Spring Boot per eseguire i test di integrazione MongoDB senza problemi.

MongoDB è un popolare database di documenti NoSQL . Grazie all'elevata scalabilità, allo sharding integrato e all'eccellente supporto della comunità è spesso considerato " lo storage NoSQL" da molti sviluppatori.

Come con qualsiasi altra tecnologia di persistenza, è fondamentale essere in grado di testare facilmente l'integrazione del database con il resto della nostra applicazione . Per fortuna, Spring Boot ci consente di scrivere facilmente quel tipo di test.

2. Dipendenze di Maven

Per prima cosa, configuriamo il genitore Maven per il nostro progetto Boot.

Grazie al genitore non abbiamo bisogno di definire manualmente la versione per ogni dipendenza Maven .

Naturalmente utilizzeremo Spring Boot:

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

Puoi trovare l'ultima versione di avvio qui.

Poiché abbiamo aggiunto il genitore Spring Boot, possiamo aggiungere le dipendenze richieste senza specificarne le versioni:

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

spring-boot-starter-data-mongodb abiliterà il supporto Spring per MongoDB:

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

de.flapdoodle.embed.mongo fornisce MongoDB incorporato per i test di integrazione.

3. Prova utilizzando MongoDB incorporato

Questa sezione copre due scenari: test Spring Boot e test manuale.

3.1. Spring Boot Test

Dopo aver aggiunto la dipendenza de.flapdoodle.embed.mongo, Spring Boot tenterà automaticamente di scaricare e avviare MongoDB incorporato durante l'esecuzione dei test.

Il pacchetto verrà scaricato solo una volta per ogni versione in modo che i test successivi vengano eseguiti molto più velocemente.

A questo punto dovremmo essere in grado di avviare e superare il test di integrazione JUnit 5 di esempio:

@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"); } }

Come possiamo vedere, il database incorporato è stato avviato automaticamente da Spring, che dovrebbe essere registrato anche nella console:

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

3.2. Test di configurazione manuale

Spring Boot avvierà e configurerà automaticamente il database incorporato, quindi inserirà l' istanza di MongoTemplate per noi. Tuttavia, a volte potrebbe essere necessario configurare manualmente il database Mongo incorporato (ad esempio, durante il test di una specifica versione di DB).

Il frammento di codice seguente mostra come configurare manualmente l'istanza MongoDB incorporata. Questo è più o meno l'equivalente del precedente test di primavera:

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"); } }

Nota, che siamo in grado di creare rapidamente MongoTemplate fagioli configurato per utilizzare il nostro database embedded configurato manualmente e registrarla all'interno del contenitore Primavera semplicemente creando, ad esempio, un @TestConfiguration con @Bean metodo che restituirà nuova MongoTemplate (MongoClients.create (connectionString, “ test ") .

Altri esempi possono essere trovati sul repository GitHub ufficiale di Flapdoodle.

3.3. Registrazione

Possiamo configurare i messaggi di registrazione per MongoDB durante l'esecuzione dei test di integrazione aggiungendo queste due proprietà al file src / test / resources / application.propertes :

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

Ad esempio, per disabilitare la registrazione, impostiamo semplicemente i valori su off :

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

3.4. Utilizzo di un database reale sulla produzione

Poiché abbiamo aggiunto la dipendenza de.flapdoodle.embed.mongo utilizzando test , non è necessario disabilitare il database incorporato durante l'esecuzione in produzione . Tutto quello che dobbiamo fare è specificare i dettagli della connessione MongoDB (ad esempio, host e porta) e siamo a posto.

Per utilizzare un DB incorporato al di fuori dei test, possiamo utilizzare i profili Spring che registreranno il MongoClient corretto (incorporato o di produzione) a seconda del profilo attivo.

Dovremo anche modificare l'ambito della dipendenza di produzione in runtime .

4. Controversia sui test incorporati

L'uso del database incorporato potrebbe sembrare un'ottima idea all'inizio. In effetti, è un buon approccio quando vogliamo testare se la nostra applicazione si comporta correttamente in aree come:

  • Configurazione della mappatura ObjectDocument
  • Listener di eventi del ciclo di vita della persistenza personalizzati (fare riferimento a AbstractMongoEventListener )
  • La logica di qualsiasi codice che lavora direttamente con il livello di persistenza

Sfortunatamente, l' utilizzo di un server incorporato non può essere considerato un "test di integrazione completa" . MongoDB incorporato di Flapdoodle non è un prodotto MongoDB ufficiale. Pertanto, non possiamo essere sicuri che si comporti esattamente come nell'ambiente di produzione.

Se vogliamo eseguire test di comunicazione nell'ambiente il più vicino possibile alla produzione, una soluzione migliore è utilizzare un contenitore di ambiente come Docker.

Per saperne di più su Docker, leggi il nostro articolo precedente qui.

5. conclusione

Spring Boot rende estremamente semplice eseguire test che verificano la corretta mappatura dei documenti e l'integrazione del database. Aggiungendo la giusta dipendenza Maven, siamo immediatamente in grado di utilizzare i componenti MongoDB nei test di integrazione di Spring Boot.

Dobbiamo ricordare che il server MongoDB incorporato non può essere considerato un sostituto di un server "reale" .

Il codice sorgente completo di tutti gli esempi è disponibile su GitHub.