这是我要测试的课程:
@Stateless
public class Finder {
@PersistenceContext(unitName = "abc")
EntityManager em;
public String read(int i) {
return this.em.find(Employee.class, i).getName();
}
}
这是单元测试:
public class FinderTest {
@Test public void testReadingWorks() {
Finder f = new Finder();
String name = f.find(1);
assert(name.length() > 0);
}
}
问题是EntityManager没有注入,在测试期间是NULL
。我做错了什么?
PS。实际上,我不明白谁确实要注入EntityManager。单元测试由JUnit在任何容器之外启动......也许我必须在测试中手动注入em
?
答案 0 :(得分:11)
EntityManagers的注入仅适用于托管bean,因为您使用new
创建Finder,不涉及容器。您可以使用EntityManagerFactory自己创建EntityManager,或使用像OpenEJB in your unit tests这样的可嵌入容器。
答案 1 :(得分:6)
实际上,我不明白究竟是谁准备注入EntityManager。单元测试由JUnit在任何容器之外启动......也许我必须在测试中手动注入em?
由于你的测试用完了容器,没有人会注入任何东西,你必须手动完成。这是恕我直言并不是一件坏事,并不难。
这是一个基类,您可以扩展它以获得EntityManager
:
public abstract class JpaBaseRolledBackTestCase {
protected static EntityManagerFactory emf;
protected EntityManager em;
@BeforeClass
public static void createEntityManagerFactory() {
emf = Persistence.createEntityManagerFactory("PetstorePu");
}
@AfterClass
public static void closeEntityManagerFactory() {
emf.close();
}
@Before
public void beginTransaction() {
em = emf.createEntityManager();
em.getTransaction().begin();
}
@After
public void rollbackTransaction() {
if (em.getTransaction().isActive()) {
em.getTransaction().rollback();
}
if (em.isOpen()) {
em.close();
}
}
}
另一种选择是在容器中运行测试,使用EJB 3.1 EJBContainer
API启动嵌入式容器。请参阅Arun的TOTD #128: EJBContainer.createEJBContainer: Embedded EJB using GlassFish v3(您需要更多的工作来设置数据源)。
或者您可以使用Arquillian。有些想法,请查看The perfect recipe for testing JPA 2: revisited。我今天早上测试了这种方法,并发现真正的集成测试非常有趣(但在容器测试中通常较慢,我不会将它们用于所有内容 - 但我开始喜欢Arquillian)。