views:

3849

answers:

3

This is a bit of an odd question, but it has been bothering me for a few months now. I have built a JPA-based web application using Wicket + Hibernate (built with Maven), and want to test the DAO layer directly. I created a specific src/test/resources/META-INF/persistence.xml file that I used for testing, but have been running into conflicts with WTP and the like. To get around these issues, I created a separate test project where the unit tests live. Is there a better way to manage unit tests for a JPA project without having duels between persistence files?

Addendum: Would other test frameworks (TestNG, for example) make this any easier?

+2  A: 

You may want to try mockito. The test works like this:

You use mockito to "implement" EntityManager. Instead of the real code, you use the methods of mockito to say "if the application calls getReference(), then return this object". In the background, mockito will create a proxy instance which intercepts the Java method calls and returns the values which you specify. Calls to other methods will return null.

Mocking things like createQuery() works the same way but you first need to create a mockup of Query and then use the same approach as in getReference() (return the query mockup).

Since you don't use a real EM, you don't need a real persistence.xml.

A much more simple solution would be if you could set some property to change the name of the persistence.xml file but I don't think that this is possible.

Some other links that may help:

Aaron Digulla
I have looked into using Mock objects (have done it for LDAP-based tests), and it is certainly an option. In this specific case I'd like to actually query the DB to validate things end-to-end, rather than just ensuring that my DAO returns information.
mlaccetti
In that case, there is a solution in the first link: You can specify several "persistence units" in the persistence.xml and select a different one in your unit tests.
Aaron Digulla
+2  A: 

We use dual persistence.xml files for production and test runtimes but it is a classpath related issue only (we use Eclipse but do not rely on WTP plugins heavily). The only difference between the two is that the production version doesn't contain entity definitions.

We don't use a mocking framework to test JPA as this wouldn't add any value to our tests. The tests do run real data access with JPA that talks to PostgreSQL database.

Our approach to tests is based on Spring test framework for persistence layer: in-transaction testing. Our application is Spring-based but this approach is equally usable for arbitrary applications that want to take advantage of Spring test classes. The essence is that each test runs within a single transaction that never commits and at the end (in tearDown) it is automatically rolled back. This solves the problem of data pollution and test dependency in very nice unobtrusive and transparent way.

The Spring test framework is flexible to allow multi-transaction testing but these are special cases that constitute not more than 10% of tests.

We still use legacy support for JUnit 3.8 but new Spring TestContext Framework for JUnit 4 looks very attractive.

For setting up in-transaction test data we use in-house utility class that constructs business entities. Since it's shared between all tests the overhead to maintain and support it is greatly outweight by the benefits of having standard and reliable way to setup test data.

Spring DI helps to make tests concise and self-descriptive but it's not a critical feature.

grigory
I have been using JUnit 4.x (4.6, at last count, I believe) and the Spring test extensions. They do help wonderfully in setting up my JPA environment, but I still have issues since my production persistence.xml references WEB-INF/lib/common-code.jar which doesn't work very well with testing.
mlaccetti
+2  A: 

Using Spring and Spring's unit testing is the best way to go. With spring, you don't require two persistence.xml's as your persistence.xml has nothing in it, everything is specified by spring (all we specify in our persistence.xml is the persistence-unit name) and thus you can change database configuration etc with spring.

And as grigory pointed out, spring's transaction based unit testing is great.

Michael Wiles
How do you specify what classes to load and what jars to dig code out of in Spring? I seem to have missed something important.
mlaccetti