Я нашел много вопросов, связанных с этим, но многие обсуждают использование баз данных 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);
}
}
Что требуется для запуска этого в моей собственной среде разработки, прежде чем принимать меры для обеспечения его правильной работы?Пожалуйста, включите ссылки на соответствующие библиотеки, которые могут помочь.
В конце я хотел бы создать формулу, которая будет использоваться для будущих проектов (я также считаю, что это является целью многих других корпоративных разработчиков).
Предлагаемая формула
Вместо того, чтобы вводить это в качестве решения и выдвигать себя в качестве того, кто дал ответ, я чувствовал, что лучше всего отметить ответ, который близко соответствует тому, что яискал и расширял его.Конфигурация - это боль, от которой я хотел получить знания, задавая этот вопрос.В конце концов, я решил положиться на Spring, чтобы справиться с кучей надоедливых вещей от нашего имени.
Прежде всего, конфигурация (при условии src/{main,test,inttest}/java
, src/{main,test,inttest}/resources
setup:
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!
}
Теперь, у этого есть слабая сторона отсутствия отката данных, поэтому я ввел хак, который удалит известные значения с помощью метода @Before
, чтобы у каждого метода было свежее известное состояние,Это может работать для некоторых, но, вероятно, не для всех.
Все отзывы приветствуются.Я бы хотел, чтобы сообщество имело хорошо документированное решение для интеграционного тестирования JPA / Hibernate, и мы все знаем, что StackOverflow - лучший первый результат в Google для наших запросов.