簡體   English   中英

使用 TestContainers 和 HikariPool-1 的 Spring 啟動 - 連接不可用,請求在 30000 毫秒后超時

[英]Spring boot with TestContainers and HikariPool-1 - Connection is not available, request timed out after 30000ms

ActiveProfiles("test")
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE)
@ContextConfiguration(initializers = AbstractIT.DockerPostgreDataSourceInitializer.class)
@Testcontainers
public abstract class AbstractIT {
    

    @SuppressWarnings("resource")
    @Container
    static PostgreSQLContainer<?> postgreSQLContainer = new PostgreSQLContainer<>("postgres:14")
            .withUsername("postgres")
            .withPassword("postgres")
            .withInitScript("sql/init.sql")
            .withDatabaseName("test")
            .withReuse(true);
    
    static {
        postgreDBContainer.start();
    }
    
    public static class DockerPostgreDataSourceInitializer implements ApplicationContextInitializer<ConfigurableApplicationContext> {
        
        @Override
        public void initialize(ConfigurableApplicationContext applicationContext) {
            
            TestPropertySourceUtils.addInlinedPropertiesToEnvironment(
                    applicationContext,
                    "spring.datasource.url=" + postgreDBContainer.getJdbcUrl(),
                    "spring.datasource.username=" + postgreDBContainer.getUsername(),
                    "spring.datasource.password=" + postgreDBContainer.getPassword()
            );
        }
    }
}

SqlExceptionHelper : HikariPool-1 - 連接不可用,請求在 30000 毫秒后超時。 ohengine.jdbc.spi.SqlExceptionHelper:連接到 localhost:49168 被拒絕。 檢查主機名和端口是否正確以及 postmaster 是否接受 TCP/IP 連接。

我創建了一個 Textcontainers 實例,我有很多集成測試,但只有一個測試類在工作,其余的則不能。 因為連接正在關閉。

安裝@DirtiesContext 並更改打開連接間隔並不能解決問題。

決定。

刪除注解@Container。


 static PostgreSQLContainer<?> postgreSQLContainer = new PostgreSQLContainer<> ......

但是,此解決方案不允許您使用數據庫。 因為當一個測試類將起作用時。 那么就會報錯說table....存在。 也就是說,測試容器將嘗試再次啟動表創建腳本。 我怎樣才能做到這一點,以便我可以重用測試容器(而不是創建一個新容器),同時我可以為所有測試節點使用一個數據庫初始化腳本?

應用程序-test.yaml

spring:
  jpa:
    show-sql: true
    hibernate:
      ddl-auto: none
    open-in-view: false
    properties:
      hibernate:
        default-schema: public
        jdbc:
          lob.non_contextual_creation: true # Fix Postgres JPA Error (Method org.postgresql.jdbc.PgConnection.createClob() is not yet implemented).
          time_zone: UTC
          # to avoid name conflict of custom table objects
          # with object names in PostgresSQL
      auto_quote_keyword: true

  test:
    database:
      replace: none
  • 基類
@ActiveProfiles("test")
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE)
@ContextConfiguration(initializers =
        SpringDataTestcontainerTests
                .DockerPostgresDataInitializer.class)
public abstract class SpringDataTestcontainerTests {

    static PostgreSQLContainer<?> postgreSQLContainer;

    static {
        postgreSQLContainer = new PostgreSQLContainer<>("postgres:14")
              .withUsername("postgres")
               .withPassword("postgres")
                .withInitScript("sql/init.sql")
               .withDatabaseName("test")
                .withReuse(true);


        postgreSQLContainer.start();
    }

    public static class DockerPostgresDataInitializer
            implements ApplicationContextInitializer<ConfigurableApplicationContext> {

        String jdbcUrl = "spring.datasource.url=" + postgreSQLContainer.getJdbcUrl();
        String username = "spring.datasource.username=" + postgreSQLContainer.getUsername();
        String password = "spring.datasource.password=" + postgreSQLContainer.getPassword();

        @Override
        public void initialize(@NotNull ConfigurableApplicationContext applicationContext) {

            TestPropertySourceUtils
                    .addInlinedPropertiesToEnvironment(applicationContext, jdbcUrl, username, password);
        }
    }

    @Autowired
    protected OrderCreateService orderCreateService;

    @Autowired
    protected OrderReadService orderReadService;

    @Autowired
    protected OrderRepository orderRepository;


    @Test
    void contextLoads() throws SQLException {

        ResultSet resultSet = performQuery(postgreSQLContainer);
        resultSet.next();
        int result = resultSet.getInt(1);
        assertEquals(1, result);

        Assertions.assertThat(postgreSQLContainer.isRunning()).isTrue();
    }

    private ResultSet performQuery(@SuppressWarnings("rawtypes") PostgreSQLContainer postgreSQLContainer)
            throws SQLException {

        String query = "SELECT 1";

        String jdbcUrl = postgreSQLContainer.getJdbcUrl();
        String username = postgreSQLContainer.getUsername();
        String password = postgreSQLContainer.getPassword();

        Connection conn = DriverManager.getConnection(jdbcUrl, username, password);
        return conn.createStatement().executeQuery(query);
    }

}

每個測試節點都以:

@TestInstance(TestInstance.Lifecycle.PER_CLASS)
class ServiceTest extends SpringDataTestcontainerTests {
}

當使用@Testcontainers@Container注解時,JUnit-Jupiter 將處理容器的生命周期,此時無需調用start() 數據源配置應該使用 DynamicPropertySource 機制注入到 Spring 上下文中。

@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@Testcontainers
public abstract class AbstractIT {
    

    @SuppressWarnings("resource")
    @Container
    static PostgreSQLContainer<?> postgreSQLContainer = new PostgreSQLContainer<>("postgres:14")
            .withUsername("postgres")
            .withPassword("postgres")
            .withInitScript("sql/init.sql")
            .withDatabaseName("test")
            .withReuse(true);
    
     @DynamicPropertySource
     static void setupProperties(DynamicPropertyRegistry registry) {
         registry.add("spring.datasource.url", postgreSQLContainer ::getJdbcUrl);
         registry.add("spring.datasource.username", postgreSQLContainer ::getUsername);
         registry.add("spring.datasource.password", postgreSQLContainer ::getPassword);
     }

}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM