gpt4 book ai didi

maven - 如何配置 Helidon 应用程序使用内存数据库进行集成测试?

转载 作者:行者123 更新时间:2023-12-05 04:19:38 25 4
gpt4 key购买 nike

我们正在设置一个 Helidon MP 应用程序,该应用程序连接到 SQL 数据库并为 CRUD 操作公开一些端点。我在实现集成测试时遇到了问题。我们的目标是让应用程序使用 SQL 数据库,但在运行测试时使用内存数据库。

  1. 我在其他框架和编程语言上使用过这种类型的实现。最初的解决方案是访问依赖注入(inject)容器并更改 ORM(在本例中为休眠)的配置以使用内存数据库。不幸的是我没能做到这一点。

  2. 第二种方法是在测试文件夹中配置另一个 persistence.xml 文件,这将覆盖主文件夹中的文件。在它们每个上使用不同的 jta-data-source,我将能够配置单独的连接凭据。我发现这会导致不明确的依赖关系并且会失败。

src/resources/META-INF/persistence.xml 的内容

<persistence>

<persistence-unit name="dservice" transaction-type="JTA">
<jta-data-source>dsource</jta-data-source>
<class>.....</class>
.
.
.
<class>.....</class>
<properties>
<property name="hibernate.dialect" value="org.hibernate.dialect.OracleDialect"/>
</properties>
</persistence-unit>

</persistence>

test/resources/META-INF/persistence.xml 的内容

<persistence>

<persistence-unit name="dservice" transaction-type="JTA">
<jta-data-source>dsource_test</jta-data-source>
<class>.....</class>
.
.
.
<class>.....</class>
<properties>
<property name="hibernate.dialect" value="org.hibernate.dialect.H2Dialect"/>
<property name="jakarta.persistence.sql-load-script-source" value="META-INF/init_script.sql"/>
<property name="jakarta.persistence.schema-generation.database.action" value="drop-and-create"/>
</properties>
</persistence-unit>

</persistence>

src/resources/META-INF/microprofile-config.properties 的内容

# used for build
oracle.ucp.jdbc.PoolDataSource.dsource.URL=jdbc:oracle:something
oracle.ucp.jdbc.PoolDataSource.dsource.connectionFactoryClassName=oracle.jdbc.pool.OracleDataSource
oracle.ucp.jdbc.PoolDataSource.dsource.user=some_user
oracle.ucp.jdbc.PoolDataSource.dsource.password=some_password

# used for in-memory testing
oracle.ucp.jdbc.PoolDataSource.dsource_test.URL=jdbc:h2:mem:depServerDb;DB_CLOSE_DELAY=-1
oracle.ucp.jdbc.PoolDataSource.dsource_test.connectionFactoryClassName=org.h2.jdbcx.JdbcDataSource
oracle.ucp.jdbc.PoolDataSource.dsource_test.user=db_user
oracle.ucp.jdbc.PoolDataSource.dsource_test.password=user_password
  1. 我在 ma​​in/resources/META-INF/persistence.xml 中添加了另一个具有不同名称的持久性单元,并尝试使用 Persistence.createEntityManagerFactory() 手动创建实体管理器并拥有一个提供者类访问实体管理器。不幸的是,这次尝试也失败了。

src/resources/META-INF/persistence.xml 的内容


<persistence>

<persistence-unit name="dservice" transaction-type="JTA">
<jta-data-source>dsource</jta-data-source>
<class>.....</class>
.
.
.
<class>.....</class>
<properties>
<property name="hibernate.dialect" value="org.hibernate.dialect.OracleDialect"/>
</properties>
</persistence-unit>


<persistence-unit name="dservice_test" transaction-type="JTA">
<jta-data-source>dsource_test</jta-data-source>
<class>.....</class>
.
.
.
<class>.....</class>
<properties>
<property name="hibernate.dialect" value="org.hibernate.dialect.H2Dialect"/>
<property name="jakarta.persistence.sql-load-script-source" value="META-INF/init_script.sql"/>
<property name="jakarta.persistence.schema-generation.database.action" value="drop-and-create"/>
</properties>
</persistence-unit>

</persistence>
  1. 我最终得到了一个我不满意的解决方案。我保留了方案 3 中的 persistence.xml 并添加了一个实体管理器提供程序类,我在其中注入(inject)了两个实体管理器,一个用于每个持久性单元。在测试类中我添加了一个@AddConfig(key = "app.testing", value = "true")。这将使我的实体管理器提供程序在应用程序运行时交付实体管理器“depservice”,并在我运行“mvn test”时交付“depservice-test” 命令。

提供者类的内容

@ApplicationScoped
public class PersistenceUnitProvider {

@PersistenceContext(unitName = "dservice")
private EntityManager em_application;

@PersistenceContext(unitName = "dservice_test")
private EntityManager em_test;

private String testing = false;

@Inject
public PersistenceUnitProvider(@ConfigProperty(name = "app.testing") String testing){
this.testing = testing;
}

public EntityManager getPersistenceUnit(){
if(this.testing == "true"){
return em_test;
}
return em_application;
}
}

将 app.testing 属性更改为 true 并使用内存数据库的 junit 测试类的内容

@HelidonTest
@AddConfig(key = "app.testing", value = "true")
class MainTest {
.
..
...
....
}

问题在于,这会使应用程序在运行或测试时建立两个连接。有没有更好的方法来实现这一点?

................................................ ..................................................... ...........................................................

更新:按照接受的答案中提到的解决方案 Laird,我们正在使用 Maven 构建过程,它具有阶段触发器来添加更改 helidon 应用程序行为所需的任何配置文件。

我们创建了一个文件夹来存放所有用于开发、测试和生产的配置文件,结构如下:

_config
development
(files that use a local SQL database)
tests
(files that use a in memory database)
production
(files that use a development SQL database)

在 pom.xml 文件中,我们根据不同阶段的需要切换配置文件

<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<executions>
<execution>
<id>copy-resources-dev</id>
<phase>compile</phase>
<goals>
<goal>copy-resources</goal>
</goals>
<configuration>
<outputDirectory>${basedir}/target/classes/META-INF</outputDirectory>
<resources>
<resource>
<directory>_config/development</directory>
<filtering>true</filtering>
</resource>
</resources>
</configuration>
</execution>

<execution>
<id>copy-resources-test</id>
<phase>test-compile</phase>
<goals>
<goal>copy-resources</goal>
</goals>
<configuration>
<outputDirectory>${basedir}/target/classes/META-INF</outputDirectory>
<resources>
<resource>
<directory>_config/tests</directory>
<filtering>true</filtering>
</resource>
</resources>
</configuration>
</execution>

<execution>
<id>copy-resources-packaging</id>
<phase>prepare-package</phase>
<goals>
<goal>copy-resources</goal>
</goals>
<configuration>
<outputDirectory>${basedir}/target/classes/META-INF</outputDirectory>
<resources>
<resource>
<directory>_config/production</directory>
<filtering>true</filtering>
</resource>
</resources>
</configuration>
</execution>
</executions>
</plugin>

这将使我们能够在运行“helidon dev”时使用本地数据库。当我们执行测试时,使用内存数据库。当我们打包应用程序并希望在某处的服务器上运行它时,请使用我们需要的任何数据库。

最佳答案

这里发生了很多很多事情。我会尽量保持简短;完整的 JPA 教程超出了这个问题和本网站的范围。

简短的回答是:(1) 在 JPA 中,一个 persistence.xml在定义上是特定于环境的,并且 (2) persistence.xml不要互相“覆盖”。这样看来,问题就简化为:我想在同一个项目中使用两个环境,但不知道如何有选择地打开和关闭它们。

有多种(非 Helidon 特定的)方法可以做这种事情:

  1. 使用maven-resources-plugin延迟复制 src/main/resources/META-INF/persistence.xml进入target/classes/META-INF/直到单元测试运行之后(因此从 persistence.xml 中的 <resources> 中排除 pom.xml,然后将 maven-resources-plugin:copy-resources goal 绑定(bind)到 prepare-package phase 。现在 src/test/resources/META-INF/persistence.xml 将在单元测试时生效,并且您的 (未经测试)src/main/resources/META-INF/persistence.xml 将是您部署的那个。
  2. 使用 MicroProfile Config 配置文件做一些了不起的事情如果您唯一需要更改的是数据源信息,它已经在 container-mode-JPA 外部 persistence.xml文件,但从您的示例来看,您似乎需要更改 <property>元素也是如此。
  3. 认识到自 persistence.xml s 本质上是特定于环境的,只是不包含 src/main/resources/META-INF/persistence.xml在您的图书馆项目中完全没有,因为根据定义,图书馆项目应该在各种环境中使用。相反,放置一个 persistence.xml在它自己的“瘦”项目中,并将那个项目与你的库项目结合起来形成一个应用程序。您当然可以通过各种其他方式测试这些组合。

关于maven - 如何配置 Helidon 应用程序使用内存数据库进行集成测试?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/74748480/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com