如何在 JEE 实体管理器中使用来自 testcontainer 的数据源

问题描述

在一个项目中,我们没有使用 spring(存在大量关于 testcontainers 的信息),而是一个相当旧的 jboss 版本 6.4.0.EAP 和 hibernate,我们无法更改。测试框架是 junit4 并且在某种程度上是 arquillian。

我尝试改进集成测试,并希望至少在数据库测试设置中使用 testcontainers。我知道如何启动 testcontainer(在那种情况下是 mysqlcontainer)以及如何运行现有的 liquibase 脚本。

我坚持的是: 如何使用数据源,我可以在这里从我启动的容器中获取

public DataSource getDataSource(MySQLContainer<?> mySQLContainer) {
    MysqlDataSource ds = new MysqlDataSource();
    ds.setUser(mySQLContainer.getUsername());
    ds.setPassword(mySQLContainer.getPassword());
    ds.setURL(mySQLContainer.getJdbcUrl());
    return ds;
}

创建一个实体管理器,然后将其注入现有的 Dao 中? 应用程序中的 Dao 定义如下

@ApplicationScoped
public class MyDao {

    @Inject
    private EntityManager entityManager;

    protected EntityManager getEM() {
        return entityManager;
    }
}

解决方法

您不将 Spring 用于您的 JEE 项目,但您只能将其用于数据源层的测试。

您需要的是:

  • 启动 mysql 作为 docker 容器
  • 使用 liqubase 应用 DDL 语句来创建表等
  • probably populate tables
  • 并在测试中访问 javax.persistence.EntityManager

这是一个简化版本,以获得一个想法:

@DataJpaTest
@TestPropertySource(properties = {"spring.jpa.hibernate.ddl-auto=validate"})
@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE)
@ContextConfiguration(initializers = { MySqlLiquibaseBaseIT.Initializer.class })
@Testcontainers
public class MySqlLiquibaseBaseIT {

  @Container
  public static MySQLContainer<?> mysql = new MySQLContainer<>(
    DockerImageName
      .parse(MySQLContainer.NAME)
      .withTag("5.7.22"));

  @Configuration
  @EnableJpaRepositories
  @EntityScan
  static class Initializer implements ApplicationContextInitializer<ConfigurableApplicationContext> {
    @Override
    public void initialize(ConfigurableApplicationContext configurableApplicationContext) {
      TestPropertyValues.of(
        "spring.datasource.url=" + mysql.getJdbcUrl(),"spring.datasource.username=" + mysql.getUsername(),"spring.datasource.password=" + mysql.getPassword(),"spring.datasource.driver-class-name=" + mysql.getDriverClassName())
        .applyTo(configurableApplicationContext.getEnvironment());
    }

    @Bean
    public SpringLiquibase springLiquibase(DataSource dataSource) {
      SpringLiquibase liquibase = new SpringLiquibase();
      liquibase.setDropFirst(true);
      liquibase.setDataSource(dataSource);
      liquibase.setChangeLog("classpath:/db/changelog/db.changelog-master.yml");
      return liquibase;
    }
  }
}

实际上我用容器做了更多有用的事情,比如:

  • mysql 自定义配置
  • 启用容器日志记录
  • sql 语句日志

The full MySqlLiquibaseBaseIT class can be found here

在您的测试中,您可以扩展它并直接使用 DataSourceEntityManager

public class ExampleEntityIT extends MySqlLiquibaseBaseIT {

  public static final long ENTITY_ID = 25L;

  @Autowired
  private DataSource dataSource;
  @Autowired
  private EntityManager entityManager;

  @Test
  public void injectedComponentsAreNotNull(){
    Assertions.assertNotNull(dataSource);
    Assertions.assertNotNull(entityManager);
  }
}

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...