How to unit testing EJBs when using JPA2?
How would you go about unit testing an EJB that uses JPA? For example, if I have an Order entity an开发者_如何学编程d and OrderEJB that is supposed to calculate the total of an order (as defined below) how would I go about unit testing the EJB without touching the database? Also, how would you define values for your entities, so you can assert the expected calculation? Here is some example code below...
@Entity
public class Order {
@Id
private long OrderId;
private LineItem[] items;
}
And an orderEJB
@Stateless
public class OrderEJB {
EntityManager em;
public double calculateOrderTotal(long orderId) { .. }
}
How would you go about unit testing the calculateOrderTotal method if I can't touch the database? I don't want to implement a DAO because I'm trying to move away from that approach.
Thanks for any help.
Isn't the general theory that OrderEJB and Order and LineItem are (if we ignore the annotation) just POJO and therefore can be tested in stand-alone JUnit? We will need to mock EntityManager, and presumably in
calculateOrderTotal()
you have some code that in concept goes
em.giveMeThisOrder(orderId)
and you just mock this. The businesss logic you're testing then gets driven by what the Mock returns. The key to this is that you must use a good mocking framework, for example JMock. In any given test you say (obviusly not with this syntax):
EntitiyManager mockEm = // create the mock
mockEm.check(that you are called with and order Id of 73)
mockEm.please( when someone calls giveMeThisOrder return then **this** particular order)
and so in each test you create exactly the order you need to exercise some aspect of your calcualtion code. You may well have many such tests that push all the edge and corner cases of your calculation.
The key idea here is Unit Test implies no external dependency such as a Database. Integration Testing could use a real database. It can be a hassle to get your mocks right, creating those Order instances can be quite dull, but it does tend to make future testing much quicker.
I do also favour doing early integration testing - you find a whole other class of errors that way.
Did you give OpenEjb a try? - If you setup in embedded mode you can pretty much run unit tests from eclipse. I have mocked out entity manager injections etc for unit testing before but then it gets tedious. With openejb you can do it with less setup. http://openejb.apache.org/
Here's what I do:
First you need to set up an in-memory database for your tests. It works just like a regular database, but it's not stored on disk. Both Derby and HsqlDB support this.
In your unit test, create an EntityManager manually, and inject it into your EJB instance. You'll probably need to keep a reference to the EntityManager so you can manage the transactions, like this:
em.getTransaction().begin();
myEjb.doSomething(x, y);
em.getTransaction().commit();
精彩评论