Spring Boot 测试,在配置中注入值
SpringBoot Test, inject value in configuration
我想做什么:
- 从测试容器开始MongoDB容器https://github.com/testcontainers/testcontainers-spring-boot/tree/develop/embedded-mongodb
- 将从启动的容器中获取的 MongoDB uri 注入到配置中
- 运行 测试
这是我的代码:
@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
配置值的方法。
这是我的解决方案,它有一点味道,因为它具有全局静态,但它至少可以工作
包装容器
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
}
}
当您使用 JUnit 5 时,您可以为 Testcontainer 使用 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。
我想做什么:
- 从测试容器开始MongoDB容器https://github.com/testcontainers/testcontainers-spring-boot/tree/develop/embedded-mongodb
- 将从启动的容器中获取的 MongoDB uri 注入到配置中
- 运行 测试
这是我的代码:
@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
配置值的方法。
这是我的解决方案,它有一点味道,因为它具有全局静态,但它至少可以工作
包装容器
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
}
}
当您使用 JUnit 5 时,您可以为 Testcontainer 使用 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。