仅用于 Spring 应用程序中的 JUnit 测试的单独数据库

Posted

技术标签:

【中文标题】仅用于 Spring 应用程序中的 JUnit 测试的单独数据库【英文标题】:Separate DB just for JUnit tests in Spring app 【发布时间】:2014-02-05 11:38:28 【问题描述】:

我正在使用文件内 HSQL 数据库为我的 Spring 应用程序编写单元测试。我不想用测试数据污染这个数据库,所以我正在尝试设置另一个内存中的 HSQL 数据库实例以用于测试。

在我的抽象测试类中,我导入测试应用程序上下文 XML 配置:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("/testingContext.xml")
@Transactional
public abstract class AbstractDaoForTesting 

testingContext.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:jdbc="http://www.springframework.org/schema/jdbc"
    xmlns:tx="http://www.springframework.org/schema/tx" xmlns:aop="http://www.springframework.org/schema/aop"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
            http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc.xsd
            http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd
                http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
    ">


    <jdbc:embedded-database id="dataSource" type="HSQL" />


        <bean id="myEmf" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
            <property name="dataSource" ref="dataSource" />
            <property name="packagesToScan" value="com.se.micom" />
            <property name="jpaVendorAdapter">
                <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter" />
            </property>
            <property name="jpaProperties">
                <props>
                    <prop key="hibernate.hbm2ddl.auto">create-drop</prop>
                    <prop key="hibernate.dialect">org.hibernate.dialect.HSQLDialect</prop>
                </props>
            </property>
        </bean>


    <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
            <property name="entityManagerFactory" ref="myEmf" />
    </bean>

    <tx:annotation-driven />

<bean id="persistenceExceptionTranslationPostProcessor" class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor" />
  <bean id="characteristicDao" class="com.se.micom.dao.CharacteristicDaoImpl"/>
  <bean id="functionalityDao" class="com.se.micom.dao.FunctionalityDaoImpl"/>
  <bean id="segmentDao" class="com.se.micom.dao.SegmentDaoImpl"/>
  <bean id="segmentService" class="com.se.micom.service.SegmentServiceImpl"/>
  <bean id="functionalityService" class="com.se.micom.service.FunctionalityServiceImpl"/>
  <bean id="characteristicService" class="com.se.micom.service.CharacteristicServiceImpl" />
</beans>

到目前为止,内存中的 HSQL db 在测试中运行良好。

然而,一旦我在我的项目中引入persistence.xml in src/main/resources/META-INF 单元测试就开始使用这个持久性单元,而不是来自testingContext.xml 的那个。

persistence.xml

<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.0" xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">

  <persistence-unit name="micomPU" transaction-type="RESOURCE_LOCAL">
    <provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
    <class>com.se.micom.dao.domain.Characteristic</class>
    <class>com.se.micom.dao.domain.Functionality</class>
    <class>com.se.micom.dao.domain.Segment</class>
    <exclude-unlisted-classes>false</exclude-unlisted-classes>
    <properties>
      <property name="javax.persistence.jdbc.url" value="jdbc:hsqldb:file:D:\workspace_java\Micom2\db\micom"/>
      <property name="javax.persistence.jdbc.password" value=""/>
      <property name="javax.persistence.jdbc.driver" value="org.hsqldb.jdbcDriver"/>
      <property name="javax.persistence.jdbc.user" value="sa"/>
    </properties>
  </persistence-unit>
</persistence>

这个配置有什么问题?为什么测试“更喜欢”使用persistence.xml中定义的db?

【问题讨论】:

【参考方案1】:

您的问题是 Spring 配置文件的完美示例。如果您希望使用某个 bean,那么让多个 bean 在您的上下文中同时做同样的事情总是有问题的。

您应该有两个不同的配置文件,"prod""test",并使用 &lt;beans profile="XYZ"&gt; ... &lt;/beans&gt; 将您的 bean 声明相应地包装在 xml 配置中。可以在here 找到更广泛的示例。

然后您可以使用 @Profile("test") 注释您的测试,它应该使用正确的数据库。

【讨论】:

以上是关于仅用于 Spring 应用程序中的 JUnit 测试的单独数据库的主要内容,如果未能解决你的问题,请参考以下文章

用于 Spring Boot 应用程序的 JUnit @BeforeClass 非静态工作

跨junit测试类重用spring应用程序上下文

用于测试的 spring junit 加载应用程序上下文

是否可以仅使用 junit 5 将 spring 安全配置加载到我的测试中?

Java 8.Spring--整合Junit测试

Java JUnit pass/failure/error区别