简体   繁体   English

Spring 集成测试与 Testcontainer - 应用程序后启动数据库

[英]Spring integration Testing with Testcontainer - Database starting after Application

My App under test with spring (core) wants to connect to a database by testcontainer, but the testcontainer is not started at this point.我的被测应用 spring(核心)想通过 testcontainer 连接到数据库,但此时 testcontainer 没有启动。 How can I achieve that the testcontainer gets ready and then the whole context ist started up?我怎样才能实现测试容器准备好然后启动整个上下文?

 import org.junit.jupiter.api.Order;
 import org.junit.jupiter.api.Test;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.test.context.junit.jupiter.web.SpringJUnitWebConfig;
 import org.testcontainers.containers.PostgreSQLContainer;
 import org.testcontainers.junit.jupiter.Container;
 import org.testcontainers.junit.jupiter.Testcontainers;

@Testcontainers
@SpringJUnitWebConfig(locations = {"classpath:it-context.xml"})
public class IntegrationTest {


    @Container
    private PostgreSQLContainer postgresqlContainer = new PostgreSQLContainer();

    @Autowired
    private StatusBean status;

    @Test
    public void appStartedSuccessful(){
        // app & database successful started and connected
        System.out.println(postgresqlContainer.getJdbcUrl());
        System.out.println(postgresqlContainer.getTestQueryString());
        System.out.println(status.getStartupTimestamp());
    }

}

You probably want to wait for the containers to start and be ready您可能希望等待容器启动并准备好

See the documentation though the code seems to indicate that the container should be waiting for a magic log entry, perhaps that's not working for you for some reason.请参阅文档,尽管代码似乎表明容器应该等待一个神奇的日志条目,也许由于某种原因这对您不起作用。

If you Thread.sleep in your test method, does the Pg container finally arrive as expected?如果您在测试方法中使用Thread.sleep ,Pg 容器最终是否按预期到达? Anything in the container logs to indicate a failure of some sort (unlikely, given the static trick worked for you).容器日志中的任何内容都表明某种故障(不太可能,因为static技巧对您有用)。

I don't see anything in the JUnit5 integration docs to indicate any manual waiting required when using @Container .我在JUnit5 集成文档中没有看到任何内容表明使用@Container时需要手动等待。

You can write your Datasource Bean class integration tests and create a datasrouce from the parameters from the postgresqlContainer您可以编写您的数据源 Bean class 集成测试,并从 postgresqlContainer 中的参数创建一个数据源

 @Configuration
    @TestInstance(TestInstance.Lifecycle.PER_CLASS)
    @Testcontainers    
    public class TestConfiguration{

       PostgreSQLContainer<?> postgres = 
             new PostgreSQLContainer<>(POSTGRES_TEST_IMAGE)
             .withInitScript("somepath/init_postgresql.sql")


            @Primary     
            @Bean     
            public DataSource dataSource(){         
            HikariConfig hikariConfig=new HikariConfig();  
            hikariConfig.setJdbcUrl(postgres.getUrl());    
            hikariConfig.setUsername(postgres.getUsername());  
            hikariConfig.setPassword(postgres.getPassword());   
            hikariConfig.setDriverClassName(postgres.getDriverClassName());         
            HikariDataSource hikariDataSource=new HikariDataSource(hikariConfig);         
            return hikariDataSource;     
            }
    }  

And import the above configuration class into your springboot test, it will automatically override the datasource with TestContainer's Postgres datasoruce.并将上面的配置 class 导入到你的 springboot 测试中,它会自动用 TestContainer 的 Postgres 数据源覆盖数据源。

Your test should look like this你的测试应该是这样的

@ExtendWith({SpringExtension.clas})
@SpringBootTest(classes = {DataSourceConfiguration.class, TestConfiguration.class})
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
@Testcontainers
public class RepoTest {

    @Autowired
    TestRepository testRepository;

    @Test
    public void testRepo() {
        System.out.println("*****************" + testRepository.existsById(1L));
    }

}

For details refer this link: https://medium.com/@arpitsharma14/testcontainer-springboot-tests-faa05b71a7dc有关详细信息,请参阅此链接: https://medium.com/@arpitsharma14/testcontainer-springboot-tests-faa05b71a7dc

In SpringBoot you will have to overwrite the DB parameter using the ones from Postgres-Testcontainer by ApplicationContextInitializer.在 SpringBoot 中,您必须使用来自 Postgres-Testcontainer 的 ApplicationContextInitializer 覆盖 DB 参数。 Testcontainers lifecycle management will handle the rest.测试容器生命周期管理将处理 rest。 Should look somehow like this:应该看起来像这样:

@Testcontainers
@SpringJUnitWebConfig(locations = {"classpath:it-context.xml"})
@ContextConfiguration(initializers = {IntegrationTest.Initializer.class})
public class IntegrationTest {

    @Container
    private static PostgreSQLContainer postgresqlContainer = new PostgreSQLContainer();

    static class Initializer implements ApplicationContextInitializer<ConfigurableApplicationContext> {
      public void initialize(ConfigurableApplicationContext configurableApplicationContext) {
        TestPropertyValues.of(
          "spring.datasource.url=" + postgres.getJdbcUrl(),
          "spring.datasource.username=" + postgres.getUsername(),
          "spring.datasource.password=" + postgres.getPassword()
        ).applyTo(configurableApplicationContext.getEnvironment());
      }
    }

    @Autowired
    private StatusBean status;

    @Test
    public void appStartedSuccessful(){
        // app & database successful started and connected
        System.out.println(postgresqlContainer.getJdbcUrl());
        System.out.println(postgresqlContainer.getTestQueryString());
        System.out.println(status.getStartupTimestamp());
    }

}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM