我目前正在开发一个 Spring Boot 应用程序,我想在其中使用 Testcontainers。一切正常,但存在阻止应用程序启动的问题。
错误消息显示:
Message: Connection to localhost:32868 refused. Check that the hostname and port are correct and that the postmaster is accepting TCP/IP connections.
我正在使用Flyway,看来主要问题与初始化Flyway bean有关:
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in class path resource [org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaConfiguration.class]: Failed to initialize dependency 'flywayInitializer' of LoadTimeWeaverAware bean 'entityManagerFactory': Error creating bean with name 'flywayInitializer' defined in class path resource [org/springframework/boot/autoconfigure/flyway/FlywayAutoConfiguration$FlywayConfiguration.class]: Unable to obtain connection from database: Connection to localhost:32868 refused. Check that the hostname and port are correct and that the postmaster is accepting TCP/IP connections.
我的测试如下:
@Testcontainers
@SpringBootTest
@AutoConfigureMockMvc
public class OwnerRestControllerTest {
// Ideally, the container should be recognized as "in use"
@Container
@ServiceConnection
static PostgreSQLContainer<?> postgresContainer =
new PostgreSQLContainer<>(DockerImageName.parse("postgres:17-alpine"));
@Autowired
private MockMvc mockMvc;
@Autowired
private OwnerRepository ownerRepository;
@Test
@Sql(scripts = "classpath:insert-owners.sql", executionPhase = Sql.ExecutionPhase.BEFORE_TEST_METHOD)
@Sql(scripts = "classpath:delete-owners.sql", executionPhase = Sql.ExecutionPhase.AFTER_TEST_METHOD)
public void getAll() throws Exception {
mockMvc.perform(get("/rest/owners")
.param("lastNameContains", "Doe"))
.andExpect(status()
.isOk())
.andExpect(jsonPath("$.content[*].lastName").value(everyItem(is("Doe"))))
.andExpect(jsonPath("$.content.length()").value(2));
}
}
我找到了解决方法,但我对此不满意。只需等待更长的时间即可:
@Testcontainers
@SpringBootTest
@AutoConfigureMockMvc
public class OwnerRestControllerTest {
@BeforeAll
static void beforeAll() throws InterruptedException {
Thread.sleep(5000);
}
}
有人遇到过类似的问题吗?对于那些感兴趣的人,我创建了一个存储库。
您可以从此分支运行应用程序:GitHub 存储库
我应该使用不同的方法来配置带有 Testcontainers 和 Flyway 的环境吗?或者这只是一个错误?
我下载了您的代码并尝试复制您的错误(没有@BeforeAll),但无法获得相同的结果(image)。无论如何,如果您仍然遇到同样的问题并且您不喜欢
Thread.sleep()
的解决方案,您可以使用注释 @DynamicPropertySource
。
@DynamicPropertySource 是一个方法级注释,可用于注册要添加到为集成测试加载的 ApplicationContext 的环境中的 PropertySource 集中的动态属性。当您事先不知道属性的值时,动态属性非常有用 - 例如,如果属性由外部资源管理,例如由 Testcontainers 项目管理的容器。
我认为您发现的问题是您的应用程序在可用之前尝试连接到 PostgreSQL 数据库 (
Unable to obtain connection from database: Connection to localhost:32868 refused
)。使用 @DynamicPropertySource
,您可以测试您的 Spring 组件,即使它依赖于数据库之类的东西。
您可以执行以下操作:
@Container
static PostgreSQLContainer<?> postgresContainer =
new PostgreSQLContainer<>("postgres:17-alpine")
.withDatabaseName("prop")
.withUsername("postgres")
.withPassword("pass");
@DynamicPropertySource
static void registerPgProperties(DynamicPropertyRegistry registry) {
registry.add("spring.datasource.url", postgresContainer::getJdbcUrl);
registry.add("spring.datasource.username", postgresContainer::getUsername);
registry.add("spring.datasource.password", postgresContainer::getPassword);
}
对于代码,我一直遵循此页面。
注意:在同一页面中,我还发现您可以使用它作为替代品
Text Fixtures
。我也尝试了该解决方案,但在这种情况下,它给了我同样的拒绝连接问题。您可以尝试实施该替代方案,看看您是否有更好的运气。