Java Reference
In-Depth Information
developed in parallel, by different teams. Using this approach, the whole business
layer could be developed and unit tested without depending on the persistence
layer, which would free the business developers from database worries. It's still nec-
essary to test everything together though, but that could be achieved through inte-
gration tests. A good compromise is to write many small (and fast) unit tests that
extensively exercise individual components and then a few (and slower) integra-
tion tests that cover the most important scenarios.
Similarly, we could test the persistence layer using mocks for the JPA interfaces. But
this approach isn't recommended, because mocks only emulate API calls, and that
wouldn't be enough, for a few reasons. First, the API is part of JPA -based development;
it's still necessary to annotate classes and provide configuration files. Second, even if
the JPA part is correctly configured, there are still third parties involved: the JPA ven-
dor (like Hibernate), the vendor's driver (such as HibernateDialect implementa-
tions) for the database being used, not to the mention the database itself. Many things
could go wrong (like vendor or drivers bugs, the use of table names that are illegal for
a given database, transaction issues, and the like) at runtime that wouldn't be
detected by using mocks for testing.
Who let the transactions out?
In a JPA-based application, it's paramount to start and commit transactions, and
the methods that use an EntityManager have two options: either they handle the
transactions themselves, or they rely on the upper layers for this dirty job. Typical-
ly, the latter option is more appropriate, because it gives the caller the option to
invoke more than one DAO method in the same transaction. Looking at our exam-
ples, UserDaoJpaImpl follows this approach, because it doesn't deal with transac-
tion management. But if you look at its caller, UserFacadeImpl , it doesn't handle
transactions either! So, in our application example, who is responsible for transac-
tion management?
The answer is the container. In our examples, we're showing pieces of an applica-
tion. But in a real project, these pieces would be assembled by a container, like a
Java EE application server or Spring, and this container would be responsible for
wrapping the Facade methods inside a JPA transaction and propagating it to the
DAO object. In our DAO test cases, we play the role of the container and explicitly
manage the transactions.
For the persistence layer, it's important to test real access to the database, as we dem-
onstrate in the next section.
18.2
Aspects of JPA testing
When you use JPA (or any other ORM software) in your application, you're delegating
the task of persisting objects to and from the database to an external tool. But in the
end, the results are the same as if you wrote the persistence code yourself. So, in its
 
 
 
 
 
 
 
 
 
 
 
 
 
Search WWH ::




Custom Search