36

This may be a naive question, but I am new to both the junit and hibernate frameworks and I was wondering what the best way to go about unit testing an application that is largely calls to hibernate, or if it is even necessary to do so?

What is the best practice here?

EDIT:
Spring seems to be the big suggestion here. Unfortunately this may be alittle too much to bite off for one project. Junit, Hibernate and Spring are all new to me, and while they are all technologies I want to get under my belt, I think trying to incorporate them all into one project may be too overwhelming for me.

Links to tutorials and/or book suggestions are welcome.

Prof. Falken
  • 24,226
  • 19
  • 100
  • 173
James McMahon
  • 48,506
  • 64
  • 207
  • 283
  • I can certainly sympathize with you about two or three of the Java buzzword technologies being to much to bite off at once. Been there, hopefully done that... :-/ – Prof. Falken May 25 '11 at 07:08
  • I would highly recommend http://javabrains.koushik.org/ for any one new to spring, hibernate. – Anmol Gupta Oct 03 '15 at 06:23

10 Answers10

19

Keep in mind the difference between unit testing and integration testing.

Unit tests should be testing code without any outside dependencies. These dependencies are mocked using a framework like, for example, JMock.

Integration tests are important too but the major drawback of them is that they take a long time to run. You can run thousands of true unit tests in a couple of seconds, but it's not the same with integration tests.

Depending on the size of your project/development team you might want to prioritize true unit tests over integration tests. Both style of tests are important but if you are pressed for resources, just going with Unit testing may be a better idea.

I wrote an application by myself that unit tested the Web (with Spring MVC this is easy) and Service layers, as well as domain objects. But I left the DAO alone because I didn't want to write a bunch of slow integration tests. If I had more people on staff I would have gone with integration tests as well, but in this case I didn't feel the time spent would be worth it.

bpapa
  • 21,409
  • 25
  • 99
  • 147
  • I've heard of Jmock before, how does one use it with Hibernate? – James McMahon Dec 30 '08 at 15:49
  • 1
    There definitely is a difference between unit tests and integration tests I agree. Just to add, there is also a difference between mockist and classical style of unit testing. it all depends on how fast (and scaled) your continuous build server is :) – Raymond Roestenburg Dec 30 '08 at 15:59
  • I concur with spending the time elsewhere. The projects I've worked on with Hibernate have always ended up with a thin layer over Hibernate and tested up to that point and mocked that layer out. If that thin layer of code is brokem it will show up real quick in sanity checks – tddmonkey Jan 06 '09 at 15:58
  • So there's really no way to tell hibernate "hey, raise when they call commit" like you can with a mock equivalent? – rogerdpack Apr 11 '12 at 16:08
  • mock tests in hibernate test barely anything useful. Avoid. Use in memory databases. – Oliver Watkins Jul 12 '18 at 15:44
5

As for best practices:

use an embedded database for running your tests if possible, so that you don't need a full deployed relational database just to run your tests (locally, or on your continuous build server if you have one). That way you also don't need to (necessarily) worry about rolling back etc, you can just recreate the database when you need to. Testing with an embedded database doesnt test peculiarities that could come up when you use your specific production database, but it does test your code, which should suffice.

You can also use DbUnit, an extension to JUnit, to easily fill the database with expected rows and put it in a known state, before you run your Hibernate tests.

Raymond Roestenburg
  • 4,890
  • 2
  • 20
  • 18
3

Best practice? I use Spring and make all my tests transactional. I perform the test and rollback all the changes so I don't change the state of the database.

duffymo
  • 305,152
  • 44
  • 369
  • 561
  • 3
    Our database's are notoriously unreliable, and even if they weren't doesn't the act of using an external system make it an integration test and not a unit test? – James McMahon Dec 30 '08 at 14:30
2

I like to use a in memory hsqldb for testing. The process for each hibernate POJO is:

  1. Create the object
  2. Persist it to the DB
  3. Clear the session
  4. Get it from the DB
  5. Assert the objects are equal.

For DAOs, I create and persist enough objects to accurately test the methods, then run the tests and delete the objects as necessary to not intefere with other tests.

jon077
  • 10,303
  • 11
  • 39
  • 37
2

Hibernate source includes a lot of unit tests, I would recommend going through those and adapting a similar approach.

You can also look at the CaveatEmptor which the sample application developed for the book "Java Persistence with Hibernate"

kamal.gs
  • 193
  • 1
  • 4
  • Is it redundant to unit test your frameworks in your application? – James McMahon Dec 30 '08 at 17:12
  • I wasn't suggesting testing hibernate, but the approach used can be adapted for your testing your application code - for example queries etc. The hibernate test suite includes such tests (though their aim is to verify that the framework works correctly). – kamal.gs Dec 30 '08 at 17:20
1

If you're using Hibernate for Domain rich models, Unit testing domain logic is as simple as testing a POJO and Hibernate doesn't get in your way. The only caveat here is, For bidirectional mappings, you might have to set the object on both sides for unit tests.

Integration testing with database is generally not done for simple mappings. However it is suggested in the case of exquisite mappings like Single table inheritance etc. The only thing to remember here is, you may have to explicitly flush to database sometimes.

Sathish
  • 20,660
  • 24
  • 63
  • 71
0

Two cases are easy to test:

  1. When practical, perform your various calculations and transformations in functions that don't know about saving or loading entities. If you can make these pure functions, so much better.

  2. For functions that only save to the database without reading from it, you can choose not to save when testing.

The simplest (crudest) way to do #2 is by adding a reallyUpdate parameter to the function, then surrounding each "save" call with:

if (reallyUpdate) {
    HibernateUtil.saveOrUpdate(theThing);
}

For me these were the lowest hanging fruit.

GlenPeterson
  • 4,866
  • 5
  • 41
  • 49
0

Sure, you'd unit test your persistence tier if it wasn't written in Hibernate, wouldn't you?

Create a given persistence interface that's implemented using Hibernate, instantiate some sample objects, perform CRUD operations, and ask JUnit to assert that the operations were successful. Same as any other class.

duffymo
  • 305,152
  • 44
  • 369
  • 561
0

You could use Spring to help here.

It has a great unit test framework, you can use it to test CRUD ops and then rollback changes - great if you don't have the capability to reload a database every time.

Fortyrunner
  • 12,702
  • 4
  • 31
  • 54
0

Write a simple layer that passes requests to Hibernate. Then use a mocking library like EasyMock or JMock to assert that your Hibernate-veneer layer is correctly called by your application classes. This is nicely described in the partially-complete JMock book (scroll down to the test smell "everything is mocked").

Douglas Squirrel
  • 2,304
  • 2
  • 19
  • 23