如何在单元测试期间注入 PersistenceContext?
Posted
技术标签:
【中文标题】如何在单元测试期间注入 PersistenceContext?【英文标题】:How to inject PersistenceContext during unit testing? 【发布时间】:2010-09-27 20:35:48 【问题描述】:这是我的 java 类:
public class Finder
@PersistenceContext(unitName = "abc")
EntityManager em;
public boolean exists(int i)
return (this.em.find(Employee.class, i) != null);
这是单元测试:
public class FinderTest
@Test public void testSimple()
Finder f = new Finder();
assert(f.exists(1) == true);
NullPointerException
测试失败,因为 Finder.em
不是由任何人注入的。我应该如何正确处理这种情况?有没有最佳实践?
【问题讨论】:
【参考方案1】:如果没有像 Spring 这样的容器(或者像 Unitils 这样基于 Spring 的容器),您将不得不手动注入实体管理器。在这种情况下,您可以使用这样的东西作为基类:
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();
【讨论】:
【参考方案2】:这取决于你想要测试的什么。当您的 Finder
类中有复杂的业务逻辑时,您可能想要模拟 EntityManager
- 使用类似 EasyMock 或 Mockito 的模拟框架 - 以便对该逻辑进行单元测试。
既然情况并非如此,我怀疑您想测试Employee
实体的持久性(这通常称为集成测试)。这需要使用数据库。为了简化测试并保持测试的可移植性,您可以为此目的使用内存数据库,例如 HSQLDB。为了启动 HSQLDB,创建一个持久化上下文并将这个上下文注入到您的 Finder 类中,建议使用像 Spring 这样的 IoC 框架。
互联网上有大量教程解释了如何使用 JPA/Spring/HSQLDB。看看这个示例项目:Integration testing with Maven 2, Spring 2.5, JPA, Hibernate, and HSQLDB
【讨论】:
我必须在每个单元测试中“手动”进行这种注入,对吧? 没有 Spring 可以解析 @PersistenceContext 注释并将其注入您的 Finder 类。您只需从 FinderTest 中引用 ApplicationContext。【参考方案3】:创建另一个包私有构造函数并仅添加 EntityManager 然后调用另一个构造函数以实现默认行为。
@PersistentContext
private EntityManager entityManager;
private ManagementService managementService;
@Autowired
public SomeClass(ManagementService managementService)
this.managementService = managementService;
SomeClass(ManagementService managementService, EntityManager entityManager)
this(managementService);
this.entityManager = entityManager;
【讨论】:
以上是关于如何在单元测试期间注入 PersistenceContext?的主要内容,如果未能解决你的问题,请参考以下文章
如何在单元测试期间覆盖 IQueryable 的 Contains 方法?