November 20, 2012

DAO Testing with Hibernate

I’m currently building some web services using Dropwizard (Jetty, Jersey, Jackson, Hibernate all bundled up), and needed to test the DAO. Dropwizard has some convenient interfaces to load configuriation files and bring up hibernate sessions, etc. when the service boots up; however, this does not translate well to JUnit tests (there’s a lot of plumbing involved in making a Service that doesn’t translate to tests.) Fortunately, though, since it’s all just sugar coating you can just as easily setup your own sessions and transactions. I found that creating a parent class for my DAO tests that does all the setup is a convenient way of handling all the plumbing you need.

Setting up Hibernate

public class DAOTests {
    SessionFactory sessionFactory;

    public DAOTests() {
        AnnotationConfiguration config=new AnnotationConfiguration();
        config.setProperty("hibernate.connection.url","jdbc:postgresql://127.0.0.1:5432/dbname");
        config.setProperty("hibernate.connection.username","username");
        config.setProperty("hibernate.connection.driver_class","org.postgresql.Driver");
        config.setProperty("hibernate.current_session_context_class", "thread");
        config.setProperty("hibernate.show_sql", "false");
        config.addAnnotatedClass(PersistableClass.class);

        sessionFactory=config.buildSessionFactory();
    }

    public Session getSession()
    {
        Session session;

        try {
            session = sessionFactory.getCurrentSession();
        } catch (SessionException se) {
            session = sessionFactory.openSession();
        }

        return session;
    }
}

Then each test suite for the DAO in question can just deal with the things it cares about, and any Hibernate-related mojo sits in the superclass. An example DAO test could look like:

Example DAO test

public class TodoDAOTest extends DAOTests {
 TodoDAO todoDAO;

 @Before
 public void initialize() {
   todoDAO = new TodoDAO(sessionFactory);

   // Delete all the old junk...
   getSession().beginTransaction();

   Query q = getSession().createQuery("delete from Todo");
   q.executeUpdate();

   getSession().getTransaction().commit();
 }

 @Test
 public void filtersTodos() throws Exception {
   getSession().beginTransaction();

   for(int i = 0; i < 10; i++)
   {
      Todo t = new Todo();
      t.setNoteId(1);
      TodoDAO.create(t);
   }

   assertEquals(TodoDAO.findAllByNoteId(1).size(), 10);

   getSession().getTransaction().commit();
 }
}