我发现了很多与此相关的问题,但很多讨论都是围绕使用 HSQL 数据库而不是配置 Eclipse 和命令行来运行实际测试。
假设我有以下虚构的场景:
@Entity
@Table("Team")
public class Team {
private Integer id;
private String name;
private String city;
private String owner;
private List<Player> players;
@Column(name="TEAM_ID")
public Integer getTeamId() {
return this.id;
}
public void setTeamId(Integer id) {
this.id = id;
}
@Column(name="TEAM_ID")
public Integer getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
// ... etc.
}
假设我们有以下数据访问层:
@Repository
public class TeamDao {
@PersistenceContext(unitName="examplePU")
EntityManger em;
public Team saveOrUpdate(Team team) {
this.em.merge(team);
}
// etc...
}
我希望能够编写类似于以下内容的集成测试:
public class TeamIntegrationTest {
@Resource
TeamDao teamDao;
@Test
public void resourceLoaded() {
assertNotNull(teamDao);
}
@Test
public void testInsertTeam() {
Team team = new Team();
team.setName("Packers");
team.setCity("Green Bay");
teamDao.saveOrUpdate(team);
}
}
在提交以确保它正常工作之前,在我自己的开发环境中运行它需要什么?请包括对可能有帮助的相关库的引用。
最后,我想创建一个可以用于 future 项目的公式(我也相信这是许多其他企业开发人员的目标)。
提议的公式
与其将此作为解决方案输入并提名自己作为提供答案的人,我觉得最好标记与我正在寻找的内容最接近的答案并对其进行扩展。配置是一种痛苦,这正是我希望通过提出这个问题来获得知识的原因。最后,我选择了依靠 Spring 来帮我们处理一堆烦人的事情。
首先,配置(假设src/{main,test,inttest}/java
, src/{main,test,inttest}/resources
设置:
src/resources/java
|
| - META-INF
| |
| | - orm.xml
| | - persistence.xml
| - applicationContext.xml
| - applicationContext-Integration.xml
orm.xml
内容不多,但是没有的时候我遇到了问题:
<?xml version="1.0" encoding="UTF-8"?>
<entity-mappings xmlns="http://java.sun.com/xml/ns/persistence/orm"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence/orm
http://java.sun.com/xml/ns/persistence/orm_1_0.xsd" version="1.0">
</entity-mappings>
Persistence.xml
包含 JPA 应该知道的实体:
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="1.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_1_0.xsd">
<persistence-unit name="persistenceUnitName">
<class>com.acme.project.className</class>
<!-- Etc... -->
</persistence-unit>
</persistence>
applicationContext.xml
包含大部分配置:
<?xml version="1.0" encoding="UTF-8"?>
<!-- Spring configuration for JPA/database/Transactions -->
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">
<context:annotation-config/>
<context:component-scan base-package="com.acme.project.full.package.name" />
<tx:annotation-driven transaction-manager="transactionManager"/>
<bean id="transactionManager"
class="org.springframework.orm.jpa.JpaTransactionManager"
p:entityManagerFactory-ref="entityManagerFactory" p:dataSource-ref="jndiDataSource"
p:jpaDialect-ref="jpaDialect" />
<bean id="jndiDataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.databaseType.jdbc.Driver" />
<property name="url" value="jdbc:url://location:port/databaseName" />
<property name="username" value="" />
<property name="password" value="" />
</bean>
<bean id="jpaDialect" class="org.springframework.orm.jpa.vendor.HibernateJpaDialect" />
<bean id="entityManagerFactory"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"
lazy-init="true" p:dataSource-ref="jndiDataSource"
p:jpaVendorAdapter-ref="hibernateJpaVendorAdapter"
p:persistenceUnitName="persistenceUnitName" p:jpaDialect-ref="jpaDialect">
</bean>
<bean id="hibernateJpaVendorAdapter"
class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"
p:databasePlatform="org.hibernate.dialect.MySQLDialect" p:generateDdl="false"
p:showSql="true" />
我们正在使用 EntityManager,因此推荐的解决方案 AbstractTransactionalDataSourceSpringContextTests不会为我们工作。相反,我们创建了以下内容以引入 SpringJUnit4ClassRunner.class
并正确设置 applicationContext。
@ContextConfiguration(locations = { "classpath:applicationContext-JPA-Integration.xml" })
@RunWith(SpringJUnit4ClassRunner.class)
public abstract class SpringBasedIntegration { }
我们创建了这个通用类,以便它可以跨其他集成测试类使用,
public class TeamIntegrationTest extends SpringBasedIntegration {
@Resource
TeamDao vitalDao;
@Before()
public void before() {
List<Team> teams = teamDao.getKnownValues("...");
for(Team entry : teams) {
vitalDao.deleteTeam(team);
}
}
@Test
public void testSomething() {
// vitalDao should be initialized with an entityManger!
}
现在,这有一个不能回滚数据的弱点,所以我引入了一个 hack,它将使用 @Before
方法删除已知值,以便每个方法都有一个新的已知状态。这可能适用于某些人,但可能不适用于所有人。
欢迎所有反馈。我希望社区拥有用于集成测试 JPA/Hibernate 的记录完备的解决方案,我们都知道 StackOverflow 是 Google 上我们查询的最佳第一结果。
最佳答案
尝试一下 Spring 框架,
您可以对 JUNIT 类使用 Spring Transactional Test;它运行测试,但在操作完成后回滚每个更改。您可以将此行为更改为实际提交,这取决于您。
神奇的是一个名为 AbstractTransactionalDataSourceSpringContextTests 的类,在您的情况下,您需要在本地项目中设置一个 applicationcontext 并使用 eclipse junit runner 运行测试。
这是一个使用 AbstractTransactionalDataSourceSpringContextTests 的好教程 http://zenoconsulting.wikidot.com/blog:8
其他链接 http://www.infoq.com/articles/testing-in-spring http://static.springsource.org/spring/docs/2.5.x/reference/testing.html#testcontext-support-classes-junit44
关于java - 使用 Hibernate/JPA 映射和 JUnit 测试 DAO 的公式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8546521/