Extending JUnit

I found that there is nice extension to JUnit called Unitils (http://www.unitils.org). It offers some generic utilities for unit testing, EasyMock mock object management, database testing (either plain JDBC or Hibernate). Also it's integrated with DBUnit and Spring.

General testing utilities

This feature set contains some things that are sometimes quite useful like reflection based equality (which we have more or less implemented ourselves in many projects I believe), ignoring order of collection elements etc. There are also some features that seem somewhat less useful like ignoring default values or asserting fields using the property path (e.g "address.street") instead of getters.

Database testing utilities

The most interesting thing here I think is the ability to test Hibernate mappings using just following statement: HibernateUnitils.assertMappingWithDatabaseConsistent(). If there are some mismatches it will generate the DDL statements that can be used to update your database schema. So to test all your mappings you only need following test case:

@SpringApplicationContext({"testContext.xml"})
public class DatabaseMappingsTest extends UnitilsJUnit4 {

  @Test
  public void objectsAreMappedCorrectly() {
      HibernateUnitils.assertMappingWithDatabaseConsistent();
  }
}

and at least following Spring beans XML in your classpath if :

<bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
  <property name="dataSource" ref="dataSource" />
  <property name="annotatedClasses">
    <list>
      <value>hibernate.domain.User</value>
      <value>hibernate.domain.Permission</value>
      ...
    </list>
  </property>
</bean>

<bean id="dataSource" class="org.unitils.database.UnitilsDataSourceFactoryBean" />

As I mentioned already Unitils integrates very nicely with Spring so in order to load Spring application context all you need is the @SpringApplicationContext annotation.

Here is a sample for testing Hibernate HQL:

@Transactional(TransactionMode.ROLLBACK)
@SpringApplicationContext({"testContext.xml"})
public class UserDaoImplTest extends UnitilsJUnit4 {
  private UserDao userDao;

  @SpringBeanByType
  private HibernateTemplate hibernateTemplate;

  @Before
  public void initDao() {
    UserDaoImpl dao = new UserDaoImpl();
    dao.setHibernateTemplate(hibernateTemplate);
    userDao = dao;
  }

  @Test
  public void save() throws Exception {
    User user = createNewTestUser();
    userDao.save(user);

    User retrieved = userDao.getUser(user.getId());
    assertEquals(user, retrieved);
  }
}

In order to get this sample working following beans need to be added to the testContext.xml

<bean id="hibernateTemplate" class="hibernate.dao.SessionFlushingHibernateTemplate">
  <property name="sessionFactory">
    <ref bean="sessionFactory" />
  </property>
</bean>

<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
  <property name="sessionFactory">
    <ref local="sessionFactory" />
  </property>
</bean>
Sidenote

Save test above is reliable only because of custom HibernateTemplate. Probably everybody already knows this that in order to test Hibernate we need to flush/clear session after every updating method because otherwise Hibernate will not send changes to database and will return exact same instance of entity the next time we try to get it from ongoing session. In AMS there is class called HibernateTemplateProxy which is doing this but it has special registry of deleted entities. Does anyone know why exactly it needs to be there? Especially as the overridden load method is only one way of materializing something from persistence.

Mock object utilities

Basically Unitils removes the need to manually create mocks and simplifies replaying and verifying. Features like injecting mocks seem a bit fishy to me but maybe I'm just too old fashioned.

Summary

In many aspects Unitils offers similar functionality that is available in Spring 2.5 test packages and probably there are some alternative unit testing libraries also. However if you can't upgrade to Spring 2.5 or want to simplify testing Hibernate/DB access code I think Unitils is quite handy.

Labels

unitils unitils Delete
junit junit Delete
testing testing Delete
hibernate hibernate Delete
spring spring Delete
Enter labels to add to this page:
Please wait 
Looking for a label? Just start typing.