Spring Boot 应用程序无法使用 Testcontainers 和 Flyway 启动

问题描述 投票:0回答:1

我目前正在开发一个 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 的环境吗?或者这只是一个错误?

java spring spring-boot flyway testcontainers
1个回答
0
投票

我下载了您的代码并尝试复制您的错误(没有@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
。我也尝试了该解决方案,但在这种情况下,它给了我同样的拒绝连接问题。您可以尝试实施该替代方案,看看您是否有更好的运气。

© www.soinside.com 2019 - 2024. All rights reserved.