Unit testing a Hibernate driven application? [clos

2020-05-14 03:34发布

问题:

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.

回答1:

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.



回答2:

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.



回答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.



回答4:

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.



回答5:

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"



回答6:

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.



回答7:

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.



回答8:

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.



回答9:

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").



回答10:

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.