To be clear it's bad idea to get EntityManagerFactory
over the Peristence.createEntityManagerFactory
inside of enterprise container, use container capability instead. If you need Peristence.createEntityManagerFactory
outside of container let say, for test only or for other reasons. You have to create Java SE JPA context, I created this example project to explain how to do it for JPA testing.
Here some project notices for better understanding, if you plan to do it by you self.
Most important part is create only one persistence.xml
, avoid to create an other one for the tests, overwrite settings of you persistence.xml
instead. This should be enough for you persistence.xml:
<persistence-unit name="application-ds" transaction-type="JTA">
<jta-data-source>java:/youApplication</jta-data-source>
<exclude-unlisted-classes>false</exclude-unlisted-classes>
</persistence-unit>
In example project I add some properties for database generation, but this not necessary maybe you have another way to prepare you database.
To create your EntityManagerFactory
, pass persistence unit name (this is important),together with properties map to Persistence.createEntityManagerFactory. With this step you set up
persistence provider for java se. It exists some limitation, first we haven't any JTA and JPA can't auto discover the entity classes.
Here the most important properties:
properties.put("javax.persistence.transactionType", "RESOURCE_LOCAL");
properties.put("javax.persistence.provider", "org.hibernate.jpa.HibernatePersistenceProvider");
properties.put("javax.persistence.jtaDataSource", null);
properties.put("hibernate.archive.autodetection", "class");
The next trick is how to inject or persistence provider into the ejb, and mockito is the solution. Code first:
@InjectMocks
private UserDao dao;
@Spy
private EntityManager em;
@Before
public void prepare() {
em = JpaProvider.instance().getEntityManager();
initMocks(this);
}
Explanation: Mockito is used to inject entity manager into the ejb. Mark EntityManager as spied object, and initialize it in @Before
test method, then call initMocks
on test class that's all.
Last but not least don't forget to create, and commit transactions, because you don't have container to do it for you.