Unitils helps you in writing simple and maintainable unit and integration tests with JUnit or TestNG.
It glues together popular test libraries like DbUnit and EasyMock and
offers integration with Spring and Hibernate.
Unitils encourages applying good practices and testing guidelines. The ideas behind
the code are based on the authors' concrete experience on enterprise projects.
In the 1.1 release, support has been added for writing tests for code that makes use
of the Java Persistence API (JPA or EJB3 persistence), in a very similar way as already
available for Hibernate. In what follows, we'll demonstrate these features using a
simple example.
Code example
Suppose we have a PersonRepository interface with an implementation based on JPA.
The PersonRepository interface has a method findByLastName and is implemented
as follows:
public class PersonRepositoryImpl implements PersonRepository {
@PersistenceContext
private EntityManager entityManager;
public List<Person> findByLastName(String lastName) {
List<Person> persons = entityManager.createQuery("find person from Person person
where person.lastName = :lastName").getResultList();
return persons;
}
}
We've written following test for this method:
@JpaEntityManagerFactory(persistenceUnit = "test", configFile = "META-INF/persistence-test.xml")
@Transactional(TransactionMode.COMMIT)
@DataSet
public class PersonRepositoryImplTest extends UnitilsJUnit4 {
@PersistenceContext
EntityManager entityManager;
PersonRepository personRepository = new PersonRepositoryImpl();
@Before
public void init() {
JpaUnitils.injectJpaResourcesInto(personRepository);
}
@Test
public void testSearchByLastName() {
List<Person> result = personRepository.findByLastName("Doe"));
ReflectionAssert.assertPropertyLenEquals("firstName", Arrays.asList("John", "Jane"),
result);
}
}
You'll notice that this test extends UnitilsJUnit4. This makes sure that while
running the test, unitils can hook into the execution of the test and inspect the
test for annotations that ask for extra behavior to be performed. For JUnit version
3.x and TestNG, we offer similar base classes called UnitilsJUnit3 and UnitilsTestNG.
JPA configuration
The @JpaEntityManagerFactory annotation tells where to find the JPA persistence config
file that needs to be loaded and the name of the persistence unit to load. If hibernate
is configured as the persistence provider, the persistence config file could look
as follows:
<persistence 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"
version="1.0">
<persistence-unit name="test">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<properties>
<property name="hibernate.dialect" value="org.hibernate.dialect.HSQLDialect"/>
<property name="hibernate.show_sql" value="true"/>
</properties>
</persistence-unit>
</persistence>
You don't need to configure the DataSource in the test persistence config file.
Under the hoods, care is taken that the JPA persistence context connects with the
test database configured in unitils.
Unitils offers a simple way to separate shared project and local configuration: common
configuration is stored in a file unitils.properties located in the classpath, and
developer specific configuration in a local file preferably stored in the user home
dir. This enables every developer to configure make sure he uses his own database
(schema). We advise to provide a test database (or schema) for each developer, which
avoids conflicts and enables each database to evolve on its own pace.
This is not the only possible way of configuring an EntityManagerFactory: If you're
using Spring, you can make use of an
EntityManagerFactory configured in a spring config file in your tests. For more information
on this subject, check the documentation.
Populating the test database with test data
Using the @DataSet annotation, we make sure that our test database is filled with
the proper test data to be able to test our query. The dataset is formatted as a DbUnit FlatXmlDataSet as
follows:
<?xml version='1.0' encoding='UTF-8'?>
<dataset>
<PERSON FIRSTNAME="John" LASTNAME="Doe" />
<PERSON FIRSTNAME="Jane" LASTNAME="Doe" />
<PERSON FIRSTNAME="Jim" LASTNAME="Smith" />
</dataset>
Entity - DB mapping test
A simple way is provided to verify the mapping of all JPA Entities with the test database,
just by using a call to JpaUnitils.assertMappingWithDatabaseConsistent(), as
in following test:
@Test
public void testMappingWithDatabase() {
JpaUnitils.assertMappingWithDatabaseConsistent()
}
Other features of unitils
Unitils offers even a lot more: By annotating tests with @Transactional, every test
is configured to run in a transaction which can be committed or rolled back at the
end. A powerful system is also offered to automatically maintain every developer's
test database.
The reflection assert utility enables checking if the resulting object matches the
expected one by scanning the complete object graph using reflection, with the ability
of ignoring fields that are null in the expected object, ignoring the type and order
of collections and the specific value of dates. In unitils 1.1, the reflection assert
utility has been improved to make sure it gives a detailed, user friendly overview
of all the differences between the expected and actual object.
If you want to learn more about unitils, check out the tutorial and cookbook.
If you have any comments, tips or questions, don't hesitate to post them on the user
forum.
Click here to see the original post