sql >> Database teknologi >  >> NoSQL >> MongoDB

Spring Boot Integration Test med Embedded MongoDB

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 test der er ingen grund til at deaktivere indlejret database, når den kører på produktion . Alt, hvad vi skal gøre, er at angive MongoDB-forbindelsesdetaljer (f.eks. vært og port), og så er vi klar.

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

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.


  1. Python-redis:Hent binære data efter en klient blev sat op med decode_responses=True

  2. Hvilken NoSQL-database skal jeg bruge til logning?

  3. Redis Python - hvordan man sletter alle nøgler i henhold til et specifikt mønster I python, uden at python itererer

  4. SQL vs NoSQL for et lagerstyringssystem