1. Oversigt
I denne vejledning lærer vi, hvordan du bruger Flapdoodles indlejrede MongoDB-løsning sammen med Spring Boot til at køre MongoDB-integrationstests problemfrit.
MongoDB er en populær NoSQL-dokumentdatabase . Takket være den høje skalerbarhed, indbyggede sharding og fremragende fællesskabssupport bliver det ofte betragtet som "den NoSQL storage” af mange udviklere.
Som med enhver anden persistensteknologi er det afgørende at være i stand til nemt at teste databaseintegration med resten af vores applikation . Heldigvis giver Spring Boot os mulighed for nemt at skrive den slags tests.
2. Maven Dependencies
Lad os først konfigurere Maven-forælderen til vores Boot-projekt.
Takket være forælderen behøver vi ikke at definere version for hver Maven-afhængighed manuelt .
Vi kommer naturligvis til at bruge 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 finde den seneste Boot-version her.
Siden vi tilføjede Spring Boot-forælder, kan vi tilføje nødvendige afhængigheder uden at angive deres versioner:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>
spring-boot-starter-data-mongodb vil aktivere Spring-understøttelse for MongoDB:
<dependency>
<groupId>de.flapdoodle.embed</groupId>
<artifactId>de.flapdoodle.embed.mongo</artifactId>
<scope>test</scope>
</dependency>
de.flapdoodle.embed.mongo leverer indlejret MongoDB til integrationstests.
3. Test ved hjælp af Embedded MongoDB
Dette afsnit dækker to scenarier:Spring Boot test og manuel test.
3.1. Spring Boot Test
Efter tilføjelse af de.flapdoodle.embed.mongo afhængighed Spring Boot vil automatisk forsøge at downloade og starte den indlejrede MongoDB når du kører test.
Pakken downloades kun én gang for hver version, så efterfølgende test kører meget hurtigere.
På dette trin burde vi være i stand til at starte og bestå prøven JUnit 5 integrationstest:
@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, blev den indlejrede database automatisk startet af Spring, som også skulle logges i konsollen:
...Starting MongodbExampleApplicationTests on arroyo with PID 10413...
3.2. Manuel konfigurationstest
Spring Boot vil automatisk starte og konfigurere den indlejrede database og derefter injicere MongoTemplate eksempel for os. Men nogle gange skal vi muligvis konfigurere den indlejrede Mongo-database manuelt (f.eks. når du tester en specifik DB-version).
Følgende uddrag viser, hvordan vi kan konfigurere den indlejrede MongoDB-instans manuelt. Dette svarer nogenlunde til den tidligere forårstest:
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");
}
}
Bemærk, at vi hurtigt kan oprette MongoTemplate bean konfigureret til at bruge vores manuelt konfigurerede indlejrede database og registrere den i Spring-beholderen ved blot at oprette, f.eks. en @TestConfiguration med @Bean metode, der returnerer ny MongoTemplate(MongoClients.create(connectionString, "test") .
Flere eksempler kan findes på det officielle Flapdoodle's GitHub-lager.
3.3. Logning
Vi kan konfigurere logningsmeddelelser for MongoDB, når vi kører integrationstests ved at tilføje disse to egenskaber til src/test/resources/application.propertes fil:
logging.level.org.springframework.boot.autoconfigure.mongo.embedded
logging.level.org.mongodb
For at deaktivere logning f.eks. sætter vi blot værdierne til fra :
logging.level.org.springframework.boot.autoconfigure.mongo.embedded=off
logging.level.org.mongodb=off
3.4. Brug af en rigtig database om produktion
Siden vi tilføjede de.flapdoodle.embed.mongo afhængighed ved hjælp af
For at bruge en indlejret DB uden for test, kan vi bruge Spring-profiler, der vil registrere den rigtige MongoClient (indlejret eller produktion) afhængigt af den aktive profil.
Vi bliver også nødt til at ændre omfanget af produktionsafhængigheden til
4. Indlejret testkontrovers
Brug af indlejret database kan se ud som en god idé i begyndelsen. Det er faktisk en god tilgang, når vi vil teste, om vores applikation opfører sig korrekt på områder som:
- Objekt<->Konfiguration af dokumenttilknytning
- Tilpasset persistence livscyklushændelseslyttere (se AbstractMongoEventListener )
- Logikken i enhver kode, der arbejder direkte med persistenslaget
Desværre kan brug af en integreret server ikke betragtes som "fuld integrationstest" . Flapdoodles indlejrede MongoDB er ikke et officielt MongoDB-produkt. Derfor kan vi ikke være sikre på, at den opfører sig præcis som i produktionsmiljøet.
Hvis vi ønsker at køre kommunikationstests i miljøet så tæt på produktionen som muligt, er en bedre løsning at bruge en miljøcontainer som Docker.
For at finde ud af mere om Docker, læs vores tidligere artikel her.