【问题标题】:SpringBoot Test, inject value in configurationSpring Boot Test,在配置中注入值
【发布时间】:2020-10-04 14:20:01
【问题描述】:

我想做什么:

这是我的代码:

@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);
    }
}

我找不到填充 spring.data.mongodb.uri 配置值的方法。

【问题讨论】:

标签: mongodb spring-boot dependency-injection testcontainers


【解决方案1】:

当您使用 JUnit 5 时,您可以为 Testcontainers 使用 JUnit Jupiter 扩展,因此您不必手动启动和停止它们(如 JUnit 4 中的 @ClassRule):

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

如果您使用 Spring Boot >= 2.2.6,他们甚至使用 @DynamicPropertySource 简化了在测试中动态设置属性的方法。

如果将两者结合起来,您的测试可能如下所示:

// @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
    }
}

如果你使用的是 JUnit 4 或 Spring Boot 2.2.6 之前的版本,我收集了不同的设置方法here

【讨论】:

    【解决方案2】:

    这是我的解决方案,因为它具有全局静态状态,所以有点味道,但至少可以工作

    包装容器

    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();
        }
    }
    

    这个东西允许在测试实例化期间覆盖属性

    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);
        }
    }
    

    这是测试

    @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
        }
    }
    

    【讨论】:

      猜你喜欢
      • 2018-11-11
      • 2017-12-21
      • 2017-04-10
      • 1970-01-01
      • 2019-03-18
      • 2021-12-28
      • 2015-09-06
      • 2019-04-30
      • 1970-01-01
      相关资源
      最近更新 更多