sql >> Databasteknik >  >> NoSQL >> MongoDB

Spring Boot Integration Testing med Embedded MongoDB

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 test det finns inget behov av att inaktivera den inbäddade databasen när den körs i produktion . Allt vi behöver göra är att ange MongoDB-anslutningsdetaljer (t.ex. värd och port) så är vi redo.

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 runtime .

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.


  1. Hur kontrollerar man om ett arrayfält innehåller ett unikt värde eller en annan array i MongoDB?

  2. Hur kan jag köra redis på en enda server på olika portar?

  3. Visualisera din klustertopologi i ClusterControl

  4. MongoDB-projektion av kapslade arrayer