答案 0 :(得分:3)
您可以覆盖@BeforeClass
中port属性的值,如下所示:
@BeforeClass
public static void beforeClass() {
System.setProperty("zookeeper.port", getRandomPort());
}
答案 1 :(得分:2)
由于在Spring Framework 5.2.5中进行了更改,因此可以使用具有相同目的的静态@DynamicPropertySource方法来替换@ContextConfiguration和ApplicationContextInitializer的使用。
@SpringBootTest
@Testcontainers
class SomeSprintTest {
@Container
static LocalStackContainer localStack =
new LocalStackContainer().withServices(LocalStackContainer.Service.S3);
@DynamicPropertySource
static void initialize(DynamicPropertyRegistry registry) {
AwsClientBuilder.EndpointConfiguration endpointConfiguration =
localStack.getEndpointConfiguration(LocalStackContainer.Service.S3);
registry.add("cloud.aws.s3.default-endpoint", endpointConfiguration::getServiceEndpoint);
}
}
答案 2 :(得分:1)
“干净”的解决方案是使用ApplicationContextInitializer
。
参见this answer,了解类似问题。
另请参见this github issue提出类似问题。
使用经过处理以保护版权持有者的真实示例总结上述文章(我有一个REST端点,该端点使用@Autowired
DataSource
,需要使用动态属性来知道内存MySQL数据库正在使用哪个端口):
@ContextConfiguration
行)。// standard spring-boot test stuff
@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@ActiveProfiles("local")
@ContextConfiguration(
classes = Application.class,
// declare the initializer to use
initializers = SpringTestDatabaseInitializer.class)
// use random management port as well so we don't conflict with other running tests
@TestPropertySource(properties = {"management.port=0"})
public class SomeSprintTest {
@LocalServerPort
private int randomLocalPort;
@Value("${local.management.port}")
private int randomManagementPort;
@Test
public void testThatDoesSomethingUseful() {
// now ping your service that talks to the dynamic resource
}
}
DatabaseObject
类建立内存数据库的示例。public class SpringTestDatabaseInitializer implements ApplicationContextInitializer<ConfigurableApplicationContext> {
private static final int INITIAL_PORT = 0; // bind to an ephemeral port
private static final String DB_USERNAME = "username";
private static final String DB_PASSWORD = "password-to-use";
private static final String DB_SCHEMA_NAME = "default-schema";
@Override
public void initialize(ConfigurableApplicationContext applicationContext) {
DatabaseObject databaseObject = new InMemoryDatabaseObject(INITIAL_PORT, DB_USERNAME, DB_PASSWORD, DB_SCHEMA_NAME);
registerShutdownHook(databaseObject);
int databasePort = startDatabase(databaseObject);
addDatabasePropertiesToEnvironment(applicationContext, databasePort);
}
private static void addDatabasePropertiesToEnvironment(ConfigurableApplicationContext applicationContext, int databasePort) {
String url = String.format("jdbc:mysql://localhost:%s/%s", databasePort, DB_SCHEMA_NAME);
System.out.println("Adding db props to environment for url: " + url);
TestPropertySourceUtils.addInlinedPropertiesToEnvironment(
applicationContext,
"db.port=" + databasePort,
"db.schema=" + DB_SCHEMA_NAME,
"db.url=" + url,
"db.username=" + DB_USERNAME,
"db.password=" + DB_PASSWORD);
}
private static int startDatabase(DatabaseObject database) {
try {
database.start();
return database.getBoundPort();
} catch (Exception e) {
throw new IllegalStateException("Failed to start database", e);
}
}
private static void registerShutdownHook(DatabaseObject databaseObject) {
Runnable shutdownTask = () -> {
try {
int boundPort = databaseObject.getBoundPort();
System.out.println("Shutting down database at port: " + boundPort);
databaseObject.stop();
} catch (Exception e) {
// nothing to do here
}
};
Thread shutdownThread = new Thread(shutdownTask, "Database Shutdown Thread");
Runtime.getRuntime().addShutdownHook(shutdownThread);
}
}
当我查看日志时,它表明对于使用该初始化器类的两个测试,它们都使用相同的对象(initialize
方法仅被调用一次,关机钩子也被调用一次)。因此,它将启动数据库,并使其保持运行状态,直到两个测试都完成,然后关闭数据库。
答案 3 :(得分:1)
从Spring Framework 5.2.5和Spring Boot 2.2.6开始,您可以在测试中使用docker-compose run python python stress_test.py
:
Dynamic Properties