【问题标题】:How to instruct Maven to ignore my main/resources/persistence.xml in favor of test/...?如何指示 Maven 忽略我的 main/resources/persistence.xml 以支持 test/...?
【发布时间】:2011-04-21 05:49:18
【问题描述】:

为了测试,我有两个persistence.xml 文件:

  • src/main/resources/META-INF/persistence.xml
  • src/test/resources/META-INF/persistence.xml

如何指示 Maven 在测试期间忽略第一个文件?现在它没有被忽略,因为 OpenEJB 说:

ERROR - FAIL ... Finder: @PersistenceContext unitName has multiple matches: 
unitName "abc" has 2 possible matches.

【问题讨论】:

  • 嗯,您能否添加有关 OpenEJB 部分的更多详细信息(可能是链接?)。因为这适用于“基本”JUnit 测试。
  • 你在使用[通过类路径发现应用程序](openejb.apache.org/3.0/…)?
  • 如果您有更多详细信息,我可以尝试给出更好的答案。您是否尝试过 altDD 方法?
  • @Pascal 是的,我正在使用“通过类路径发现应用程序”,并且我一直看到此错误消息。我其实可以理解是怎么回事,classpath中有两个persistence.xml,OpenEJB搞糊涂了..

标签: java maven-2 openejb


【解决方案1】:

查看alternate descriptors 功能,该功能针对您正在尝试做的事情。

试试这个设置:

  • src/main/resources/META-INF/persistence.xml
  • src/main/resources/META-INF/test.persistence.xml

然后您可以通过将openejb.altdd.prefix System 或 InitialContext 属性设置为test 来构造OpenEJB 以首选test.persistence.xml 文件

另一个可能的解决方案是override the persistence unit properties in the test。使用这种方法,您可以避免需要第二个persistence.xml,这很好,因为维护两个可能会很痛苦。

您可以使用 Maven 方法,但请注意,根据规范,持久性提供程序只会在找到 persistence.xml 的确切 jar 或目录中查找(也称为扫描)@Entity bean。所以要敏锐地意识到在 Maven 中这是两个不同的位置:

  • target/classes
  • target/test-classes

编辑更多关于覆盖能力的细节

您可以通过系统属性或初始上下文属性(包括 jndi.properties 文件)覆盖测试设置中的任何属性。格式为:

<unit-name>.<property>=<value>

例如使用以下persistence.xml

<persistence>
  <persistence-unit name="movie-unit">
    <provider>org.hibernate.ejb.HibernatePersistence</provider>
    <jta-data-source>movieDatabase</jta-data-source>
    <non-jta-data-source>movieDatabaseUnmanaged</non-jta-data-source>
    <properties>
      <property name="hibernate.hbm2ddl.auto" value="create-drop"/>
      <property name="hibernate.max_fetch_depth" value="3"/>
    </properties>
  </persistence-unit>
</persistence>

您可以在测试用例中覆盖添加持久性单元属性。目前没有删除它们的设施(如果您需要,请告诉我们——到目前为止还没有真正出现)。

Properties p = new Properties();
p.put(Context.INITIAL_CONTEXT_FACTORY,"org.apache.openejb.client.LocalInitialContextFactory");

p.put("movie-unit.hibernate.hbm2ddl.auto", "update");
p.put("movie-unit.hibernate.dialect", "org.hibernate.dialect.HSQLDialect");

context = new InitialContext(p);

或者通过jndi.properties文件

java.naming.factory.initial=org.apache.openejb.client.LocalInitialContextFactory
movie-unit.hibernate.hbm2ddl.auto = update
movie-unit.hibernate.dialect = org.hibernate.dialect.HSQLDialect

【讨论】:

  • 是的,我使用的是 Maven,严格区分生产persistence.xml 和测试persistence.xml 很重要。这就是为什么我强烈反对将test.persistence.xml 放入src/main/resources 的想法。
  • 从您其他帖子的外观来看,您似乎可以轻松摆脱上面链接的覆盖选项。这是更理想的选择,因为维护两个 persistence.xml 文件很痛苦。
  • 替代描述解决方案真的适用于 persistence.xml 文件吗?根据文档,它看起来并非如此。另外,我自己对此进行了快速测试,但没有成功。
【解决方案2】:

我认为您可以在 pom.xml 中创建两个配置文件:

<properties>
  <environment>dev</environment>
</properties>
<profiles>
  <profile>
    <id>prod</id>
    <properties>
      <environment>test</environment>
    </properties>
  </profile>
</profiles>

之后,在您的 src 文件夹中,创建两个名为 dev/resoruces 和 test/resources 的文件夹,并将您的不同资源复制到那里。之后,添加如下内容:

<resources>
  <resource>
    <directory>${basedir}/src/main/resources</directory>
    <filtering>false</filtering>
  </resource>
  <resource>
    <directory>${basedir}/src/main/${environment}/resources</directory>
    <filtering>true</filtering>
  </resource>
</resources>

${basedir} 取决于命令行参数,它可以是 test 或 dev。 你像这样运行 maven 命令:mvn clean package -P test

【讨论】:

  • 看起来像一个非常“肮脏”的解决方案,因为我必须始终记住,测试将使用 mvn test -P test 运行,而不是像往常一样 mvn test...
【解决方案3】:

我一直在测试这些和其他类似的解决方案,而不涉及 pom.xml...在我看来,解决这个问题的最佳方法是拥有两个 application-context.xml(一个只用于测试类) 并在测试的 application-context.xml 中添加自定义持久性单元管理器 bean。像这个例子:

<bean id="pum" class="org.springframework.orm.jpa.persistenceunit.DefaultPersistenceUnitManager">
  <property name="persistenceXmlLocation">
     <value>classpath*:META-INF/test.persistence.xml</value>
  </property>
  <property name="defaultDataSource" ref="dataSource"/>
</bean>

此解决方案运行。 :)

【讨论】:

    【解决方案4】:

    最好同时添加这两个文件 - 通常,在构建中区分测试/生产或调试/配置文件/生产只会带来麻烦。 最好尝试为生产(比如 abc-production)和测试(abc-tests)使用不同的持久化单元名称。

    【讨论】:

    • @iiekm 如果有两个不同的单元名称 - 我如何通过 unitName 自动注入 EntityManager 来运行单元测试?
    • 我从来没有使用过@PersistenceContext,所以我不会在Spring中告诉你——只需创建两个Spring XML文件;让一个用于常规应用程序(您通常在 web.xml 中选择它),另一个用于测试(您在测试代码中选择它);让用于生产的一个使用持久化上下文 abc-production 创建一个 EntityManager,另一个使用 abc-tests
    猜你喜欢
    • 2013-05-11
    • 2015-03-22
    • 1970-01-01
    • 1970-01-01
    • 2011-02-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-02-07
    相关资源
    最近更新 更多