1. Översikt
I den här handledningen lär vi oss hur du använder Flapdoodles inbäddade MongoDB-lösning tillsammans med Spring Boot för att köra MongoDB-integreringstester smidigt.
MongoDB är en populär NoSQL-dokumentdatabas . Tack vare den höga skalbarheten, inbyggda sönderdelningen och utmärkt communitysupport anses det ofta vara "den NoSQL-lagring” av många utvecklare.
Som med alla andra beständighetsteknologier är det viktigt att enkelt kunna testa databasintegrering med resten av vår applikation . Tack och lov låter Spring Boot oss enkelt skriva den typen av tester.
2. Maven Dependens
Låt oss först ställa in Maven-föräldern för vårt Boot-projekt.
Tack vare föräldern behöver vi inte definiera version för varje Maven-beroende manuellt .
Vi kommer naturligtvis att använda Spring Boot:
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.6.1</version>
<relativePath /> <!-- lookup parent from repository -->
</parent>
Du kan hitta den senaste startversionen här.
Eftersom vi lade till Spring Boot-förälder kan vi lägga till nödvändiga beroenden utan att ange deras versioner:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>
spring-boot-starter-data-mongodb kommer att aktivera Spring-stöd för MongoDB:
<dependency>
<groupId>de.flapdoodle.embed</groupId>
<artifactId>de.flapdoodle.embed.mongo</artifactId>
<scope>test</scope>
</dependency>
de.flapdoodle.embed.mongo tillhandahåller inbäddad MongoDB för integrationstester.
3. Testa med Embedded MongoDB
Det här avsnittet täcker två scenarier:Spring Boot-test och manuellt test.
3.1. Spring Boot Test
Efter att ha lagt till de.flapdoodle.embed.mongo dependency Spring Boot försöker automatiskt ladda ner och starta den inbäddade MongoDB när du kör tester.
Paketet kommer bara att laddas ner en gång för varje version så att efterföljande tester går mycket snabbare.
I detta skede bör vi kunna starta och klara provet JUnit 5-integreringstestet:
@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");
}
}
Som vi kan se startades den inbäddade databasen automatiskt av Spring, som också bör loggas i konsolen:
...Starting MongodbExampleApplicationTests on arroyo with PID 10413...
3.2. Manuell konfigurationstest
Spring Boot kommer automatiskt att starta och konfigurera den inbäddade databasen och sedan injicera MongoTemplate exempel för oss. Men ibland kan vi behöva konfigurera den inbäddade Mongo-databasen manuellt (t.ex. när du testar en specifik DB-version).
Följande utdrag visar hur vi kan konfigurera den inbäddade MongoDB-instansen manuellt. Detta motsvarar ungefär det tidigare vårtestet:
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");
}
}
Observera att vi snabbt kan skapa MongoTemplate bean konfigurerad för att använda vår manuellt konfigurerade inbäddade databas och registrera den i Spring-behållaren genom att bara skapa, t.ex. en @TestConfiguration med @Bean metod som returnerar nya MongoTemplate(MongoClients.create(connectionString, “test”) .
Fler exempel finns på det officiella Flapdoodles GitHub-förråd.
3.3. Loggning
Vi kan konfigurera loggningsmeddelanden för MongoDB när vi kör integrationstester genom att lägga till dessa två egenskaper till src/test/resources/application.propertes fil:
logging.level.org.springframework.boot.autoconfigure.mongo.embedded
logging.level.org.mongodb
För att till exempel inaktivera loggning ställer vi helt enkelt in värdena på av :
logging.level.org.springframework.boot.autoconfigure.mongo.embedded=off
logging.level.org.mongodb=off
3.4. Använda en riktig databas om produktion
Sedan vi lade till de.flapdoodle.embed.mongo beroende med
För att använda en inbäddad DB utanför tester kan vi använda Spring-profiler som registrerar rätt MongoClient (inbäddad eller produktion) beroende på den aktiva profilen.
Vi måste också ändra omfattningen av produktionsberoendet till
4. Inbäddad testkontrovers
Att använda inbäddad databas kan se ut som en bra idé i början. Det är faktiskt ett bra tillvägagångssätt när vi vill testa om vår applikation fungerar korrekt inom områden som:
- Objekt<->Konfiguration av dokumentmappning
- Anpassad beständighet livscykelhändelselyssnare (se AbstractMongoEventListener )
- Logiken i vilken kod som helst som arbetar direkt med beständighetslagret
Tyvärr kan användning av en inbäddad server inte betraktas som "full integrationstestning" . Flapdoodles inbäddade MongoDB är inte en officiell MongoDB-produkt. Därför kan vi inte vara säkra på att den beter sig exakt som i produktionsmiljön.
Om vi vill köra kommunikationstester i miljön så nära produktionen som möjligt är en bättre lösning att använda en miljöcontainer som Docker.
För att ta reda på mer om Docker, läs vår tidigare artikel här.