0

What Im' trying to do:

Here is my code:

@ExtendWith({SpringExtension.class})
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, properties = {
        "embedded.mongodb.install.enabled=true",
        "spring.data.mongodb.uri=mongodb://${embedded.mongodb.host}:${embedded.mongodb.port}/${embedded.mongodb.database}"
})
@AutoConfigureMockMvc
@ImportAutoConfiguration
class UploadFileControllerTest {

    @LocalServerPort
    private int port;

    @Autowired
    private MockMvc mockMvc;

    @Autowired
    private ObjectMapper objectMapper;

    private static MongoDBContainer mongoDbContainer;

    @BeforeAll
    public static void startContainer() {
        mongoDbContainer = new MongoDBContainer();

        mongoDbContainer.start();
        // !!! this one should be injected into spring.data.mongodb.uri
        System.out.println("mongoURL: " + mongoDbContainer.getReplicaSetUrl());
        // !!!
    }

    @AfterAll
    public static void stopContainer() {
        mongoDbContainer.stop();
    }

    @Test
    void testUploadAndParseFile() throws Exception {
        var fileUploadTask = uploadFileUsingMockMvc(zipFile);
        System.out.println(fileUploadTask);
    }
}

I cant' find a way to populate spring.data.mongodb.uri configuration value.

Capacytron
  • 3,425
  • 6
  • 47
  • 80

2 Answers2

3

As you are using JUnit 5, you can use a JUnit Jupiter extension for Testcontainers, so you don't have to manually start and stop them (like @ClassRule in JUnit 4):

<dependency>
  <groupId>org.testcontainers</groupId>
  <artifactId>junit-jupiter</artifactId>
  <version>${testcontainers.version}</version>
  <scope>test</scope>
</dependency>

and if you use Spring Boot >= 2.2.6 they even simplified the way to set properties dynamically in a test using @DynamicPropertySource.

If you combine both, your test can look like the following:

// @ExtendWith({SpringExtension.class}) not needed, already part of @SpringBootTest
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@AutoConfigureMockMvc
@ImportAutoConfiguration
@Testcontainers // this is new
class UploadFileControllerTest {

    @LocalServerPort
    private int port;

    @Autowired
    private MockMvc mockMvc;

    @Autowired
    private ObjectMapper objectMapper;

    @Container
    private static MongoDBContainer mongoDbContainer = new MongoDBContainer();

    @DynamicPropertySource
    static void mongoDbProperties(DynamicPropertyRegistry registry) {
      registry.add("spring.data.mongodb.uri", mongoDbContainer::getUri);
    }


    @Test
    void testStuffWithMongo() throws Exception {
     // bla-bla-bla
    }
}

If you are using JUnit 4 or a version of Spring Boot before 2.2.6, I've collected different setup methods here.

rieckpil
  • 10,470
  • 3
  • 32
  • 56
0

here is my solution, it smells a bit since it has global static state, but it works at least

Wrap container

public class MongoDbContainerEntryPoint {

    private static MongoDBContainer mongoDbContainer = new MongoDBContainer();

    public static void start() {
        mongoDbContainer.start();
    }

    public static void stop() {
        mongoDbContainer.stop();
    }

    public static String getUri() {
        return mongoDbContainer.getReplicaSetUrl();
    }
}

This thing allows to override properties during test instantiation

public class MongoDBContextInitializer implements
        ApplicationContextInitializer<ConfigurableApplicationContext> {

    @Override
    public void initialize(ConfigurableApplicationContext ac) {

        ConfigurableEnvironment ce = ac.getEnvironment();
        System.out.println("Setting to configuration: " + MongoDbContainerEntryPoint.getUri());
        TestPropertyValues values = TestPropertyValues.of(
                "spring.data.mongodb.uri=" + MongoDbContainerEntryPoint.getUri()
        );
        values.applyTo(ac);
    }
}

Here is the test

@ExtendWith({SpringExtension.class})
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@ContextConfiguration(initializers = MongoDBContextInitializer.class)
@AutoConfigureMockMvc
@ImportAutoConfiguration
class UploadFileControllerTest {

    @LocalServerPort
    private int port;

    @Autowired
    private MockMvc mockMvc;

    @Autowired
    private ObjectMapper objectMapper;


    @BeforeAll
    public static void startContainer() {
        MongoDbContainerEntryPoint.start();
    }

    @AfterAll
    public static void stopContainer() {
        MongoDbContainerEntryPoint.stop();
    }

    @Test
    void testStuffWithMongo() throws Exception {
     // bla-bla-bla
    }
}
Capacytron
  • 3,425
  • 6
  • 47
  • 80