1. Overzicht
In deze zelfstudie leren we hoe we de ingebouwde MongoDB-oplossing van Flapdoodle samen met Spring Boot kunnen gebruiken om MongoDB-integratietests soepel uit te voeren.
MongoDB is een populaire NoSQL-documentdatabase . Dankzij de hoge schaalbaarheid, ingebouwde sharding en uitstekende community-ondersteuning wordt het vaak beschouwd als "de NoSQL-opslag” door veel ontwikkelaars.
Zoals met elke andere persistentietechnologie, is het van cruciaal belang om de database-integratie met de rest van onze applicatie eenvoudig te kunnen testen . Gelukkig stelt Spring Boot ons in staat om dat soort tests gemakkelijk te schrijven.
2. Maven-afhankelijkheden
Laten we eerst de Maven-ouder instellen voor ons Boot-project.
Dankzij de ouder hoeven we de versie voor elke Maven-afhankelijkheid niet handmatig te definiëren .
We gaan natuurlijk Spring Boot gebruiken:
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.6.1</version>
<relativePath /> <!-- lookup parent from repository -->
</parent>
Je kunt de nieuwste Boot-versie hier vinden.
Sinds we Spring Boot-ouder hebben toegevoegd, kunnen we vereiste afhankelijkheden toevoegen zonder hun versies op te geven:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>
spring-boot-starter-data-mongodb zal Spring-ondersteuning voor MongoDB inschakelen:
<dependency>
<groupId>de.flapdoodle.embed</groupId>
<artifactId>de.flapdoodle.embed.mongo</artifactId>
<scope>test</scope>
</dependency>
de.flapdoodle.embed.mongo biedt embedded MongoDB voor integratietests.
3. Test met ingesloten MongoDB
Deze sectie behandelt twee scenario's:Spring Boot-test en handmatige test.
3.1. Spring Boot Test
Na het toevoegen van de.flapdoodle.embed.mongo afhankelijkheid Spring Boot zal automatisch proberen de ingesloten MongoDB te downloaden en te starten bij het uitvoeren van tests.
Het pakket wordt voor elke versie slechts één keer gedownload, zodat volgende tests veel sneller verlopen.
In dit stadium zouden we in staat moeten zijn om de voorbeeld JUnit 5 integratietest te starten en te halen:
@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");
}
}
Zoals we kunnen zien, is de ingebedde database automatisch gestart door Spring, die ook in de console moet worden ingelogd:
...Starting MongodbExampleApplicationTests on arroyo with PID 10413...
3.2. Handmatige configuratietest
Spring Boot start en configureert automatisch de ingesloten database en injecteert vervolgens MongoTemplate bijvoorbeeld voor ons. soms moeten we de ingebouwde Mongo-database echter handmatig configureren (bijv. bij het testen van een specifieke DB-versie).
Het volgende fragment laat zien hoe we de ingesloten MongoDB-instantie handmatig kunnen configureren. Dit is ongeveer het equivalent van de vorige voorjaarstest:
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;
ImmutableMongodConfig mongodConfig = MongodConfig
.builder()
.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");
}
}
Merk op dat we snel MongoTemplate kunnen maken bean geconfigureerd om onze handmatig geconfigureerde ingesloten database te gebruiken en deze te registreren in de Spring-container door simpelweg een @TestConfiguration te maken met @Bean methode die nieuwe MongoTemplate(MongoClients.create(connectionString, "test") retourneert .
Meer voorbeelden zijn te vinden op de officiële Flapdoodle's GitHub-repository.
3.3. Loggen
We kunnen logberichten voor MongoDB configureren bij het uitvoeren van integratietests door deze twee eigenschappen toe te voegen aan src/test/resources/application.propertes bestand:
logging.level.org.springframework.boot.autoconfigure.mongo.embedded
logging.level.org.mongodb
Om bijvoorbeeld logboekregistratie uit te schakelen, stellen we de waarden eenvoudig in op uit :
logging.level.org.springframework.boot.autoconfigure.mongo.embedded=off
logging.level.org.mongodb=off
3.4. Een echte database over productie gebruiken
Sinds we de.flapdoodle.embed.mongo hebben toegevoegd afhankelijkheid met behulp van
Om een embedded DB buiten tests te gebruiken, kunnen we Spring-profielen gebruiken die de juiste MongoClient registreren (embedded of productie) afhankelijk van het actieve profiel.
We moeten ook het bereik van de productie-afhankelijkheid wijzigen in
4. Ingebedde testcontroverse
Het gebruik van een ingesloten database lijkt in het begin misschien een geweldig idee. Het is inderdaad een goede benadering wanneer we willen testen of onze applicatie zich correct gedraagt op gebieden zoals:
- Object<->Configuratie documenttoewijzing
- Aangepaste luisteraars voor levenscyclusgebeurtenissen voor persistentie (raadpleeg AbstractMongoEventListener )
- De logica van elke code die rechtstreeks met de persistentielaag werkt
Helaas kan het gebruik van een embedded server niet worden beschouwd als “volledige integratietest” . De ingebouwde MongoDB van Flapdoodle is geen officieel MongoDB-product. Daarom kunnen we er niet zeker van zijn dat het zich precies zo gedraagt als in de productieomgeving.
Als we communicatietesten in de omgeving zo dicht mogelijk bij de productie willen uitvoeren, is een betere oplossing om een omgevingscontainer zoals Docker te gebruiken.
Lees hier ons vorige artikel voor meer informatie over Docker.