9

So, I'm developing some database-driven RESTful Java web services, using Hibernate and MySQL. For testing purposes, I'm using the H2 in-memory database. H2 is nice and fast, so this has worked out really well. The only problem is that populating the DB tables prior to my tests is sort of tedious. I basically create and persist a bunch of objects by hand. I'm wondering if maybe I'm going down the wrong road.

Please tell me, what are the best practices for doing what I'm trying to do? Any tools that could help me? Any general strategies or tips?

4 Answers 4

4

I'm going to assume you've designed your API so you can DI your DB details, if not then we can help you through that.

In terms of terminology, you're wanting to use a Fake Test Double. In this particular case, I'd recommend using the same in-memory DB (H2), but use DBUnit to work with JUnit in order to create your tables, populate them before each test, truncate the data after each test and then finally teardown the tables once your TestSuite is finished.

There are other solutions such as Grails and Spring Roo which create some test data for you, but DBUnit will work a treat for you now.

9
  • +1 for DBUnit. Makes unit testing DB code sooo much more pleasant.
    – TMN
    Commented Jul 21, 2011 at 20:03
  • Cool -- I'll definitely check that out. Right now, I'm telling Hibernate to auto-create the tables, using the hibernate.hbm2ddl.auto=create-drop property. Will that work with DBUnit, or should I stop doing this?
    – sangfroid
    Commented Jul 21, 2011 at 21:30
  • It'll work with it yes - in fact one of the ways to mimic DBUnit is to simply insert data as POJOs through Hibernate Commented Jul 21, 2011 at 21:34
  • Awesome! Okay, I'm going to check this out.
    – sangfroid
    Commented Jul 21, 2011 at 23:47
  • Also, is it necessary to use DI for this? Right now I have a persistance.xml in my /main/resources/META-INF folder that specifies my acutal DB server, and a persistance.xml in my /test/resources/META-INF folder that specifies H2. This seems to work really well. In general, I'm super-ultra-100% confused about Spring -- I've never used it before and don't understand how it could help me here, even though everyone says I should use it.
    – sangfroid
    Commented Jul 21, 2011 at 23:58
1

Perhaps you would benefit by utilizing a mocking framework in your automated unit tests?

There are a number of different ones to choose from:

4
  • Yes, I already use Mockito for unit tests. But I also want to do (integration?) tests that reach out to the DB.
    – sangfroid
    Commented Jul 21, 2011 at 19:13
  • +1 for suggesting mocking frameworks over database solutions. The database approach introduces frequently unnecessary complexity which mostly ends up testing Hibernate rather than your DAOs. Also, I'd add JMockit in that list - it does everything. Immutable String? I don't think so.
    – Gary
    Commented Jul 21, 2011 at 20:19
  • 1
    Well, I should mention that I'm new to Hibernate. So it actually is important for me to test that I've done all my hibernate stuff correctly. Also, it seems like a lot of operations couldn't be tested with a mocking framework. For example, you have a method that returns a bunch of records. How can you test that method actually returns a bunch of records if you don't have a database for it to run against?
    – sangfroid
    Commented Jul 21, 2011 at 23:47
  • @sangfroid, This is a good point and something I can benefit from too. Hibernate logic and HQL queries specifically don't unit test well in the traditional sense. In the past I depended on integration unit tests to verify the functionality but these were nearly always environment specific and brittle. DBUnit was mentioned in a previous answer and looks like it deserves a second look.
    – maple_shaft
    Commented Jul 22, 2011 at 11:03
1

All you can really do is persist objects by hand or have a prebuilt database that you load. You also need to make sure that the database is reset after each test.

In a project I'm working on I'm new to Hibernate so I have a bunch of tests for basic relationship and cascade operations. Using TestNG I have a GenericHbTest class that all Hibernate tests extend from. It has a @BeforeMethod method that re-exports the db schema and a few utility methods for generating various DAO objects. This allows me to tailor an environment for each test.

The only disadvantage to re-exporting the schema each test is that it takes a really long time to finish running tests. But I just need to be sure that everything is separate and clean. If your more experienced with Hibernate and have a more stable schema then re-exporting before every test is probably unnecessary. At least though clear all the tables beforehand

1

Have you considered object serialization? This is the fastest and easiest method I used.

It consist of creating the state you want, serialize it to disk. You use those files to populate the in-memory database you use for your tests.

One of the advantage is that you can edit the files manually later.

As an alternative, if you are well organized in your unit tests, you could create object generators. When the tests start the database is instantiated and schema is exported (using nHibernate). Objects are generated and populated in the database.

This method has an advantage over the first one: your object generators evolve with your code, so you don't need to worry about your files like in previous suggestion.

1
  • +1 for an interesting approach, but it could be a bit fragile.
    – Gary
    Commented Jul 21, 2011 at 20:21

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.