如何使用 JPA 实现测试 DAO?

Posted

技术标签:

【中文标题】如何使用 JPA 实现测试 DAO?【英文标题】:How to test a DAO with JPA implementation? 【发布时间】:2011-01-30 01:05:10 【问题描述】:

我来自 Spring 阵营,我不想使用 Spring,正在迁移到 JavaEE6, 但我在测试 DAO + JPA 时遇到问题,这是我的简化示例:

public interface PersonDao

  public Person get(long id);

这是一个很基础的DAO,因为我是Spring出来的,相信DAO还是有它的价值的,所以决定加一个DAO层。

public class PersonDaoImpl implements PersonDao , Serializable

  @PersistenceContext(unitName = "test", type = PersistenceContextType.EXTENDED)
  EntityManager entityManager ;

  public PersonDaoImpl()
  
  

  @Override
  public Person get(long id)
  
    return entityManager .find(Person.class , id);
  

这是一个 JPA 实现的 DAO,我希望 EE 容器或测试容器能够注入 EntityManager(就像 Spring 一样)。

public class PersonDaoImplTest extends TestCase

  @Inject 
  protected PersonDao personDao;

  @Override
  protected void setUp() throws Exception
  
    //personDao = new PersonDaoImpl();
  

  public void testGet()
  
    System.out.println("personDao = " + personDao); // NULL !
    Person p = personDao.get(1L);
    System.out.println("p = " + p);
  

这是我的测试文件。

好的,问题来了: 因为 JUnit 不理解 @javax.inject.Inject ,所以 PersonDao 将无法注入,测试将失败。

如何找到能够将 EntityManager 注入 PersonDaoImpl 并将 PersonDaoImpl 注入到 TestCase 的 PersonDao 的测试框架?

我试过 unitils.org ,但找不到这样的样本,它只是直接将 EntityManagerFactory 注入到 TestCast ,而不是我想要的......

【问题讨论】:

【参考方案1】:

因为我来自Spring,我相信DAO还是有它的价值的,所以我决定加一个DAO层。

我真的不明白 Spring 与此有什么关系。我不同意as I wrote in a previous answer。对我来说,JPA 是一个 DAL(数据访问层),我看不出将数据访问层置于另一个数据访问层之上的意义。至少不是系统的。但是我们不要讨论这个。

这是一个 JPA 实现的 DAO,我希望 EE 容器或测试容器能够注入 EntityManager(就像 Spring 一样)。

如果您的 DAO 是像 CDI 托管 bean 这样的托管组件,那么 Java EE 容器应该能够在其中注入 EntityManager

对于容器管理对象的单元测试,您不需要任何类型的容器。对于集成测试,您将需要某种容器,就像您对 Spring bean、Hibernate/JPA 实体、会话 bean、CDI 托管 bean 或任何其他类型的容器托管对象所做的那样。你可以use the EJB3.1 embeddable API in your tests。也可以看看Arquillian。

【讨论】:

至于 JPA 是否杀死了 DAO,这取决于。在某些时候,您想在某处重构 JPA 代码,以便可以在其他地方重用它。那么还有什么比 DAO 更好的地方呢? @BalusC 我不同意“系统地使用 DAO”,但我同意“这取决于”......但不完全是因为你给出的原因(我不是说你是错了,但我想看看你的例子的具体说明,我在可视化它时遇到了一些困难)。 还没有,我还没有在实际项目中使用过 JPA,只是对它感兴趣。但我可以想象,每当你需要重复相同的一堆 JPA 代码行时,如果它超过 3~5 行代码左右,你想重构它,我还无法想象“正确”放置这些行的地方。它是 DAO 类吗?【参考方案2】:

您也可以添加方法PersonDaoImpl.setEntityManager(EntityManager em),然后通过Persistence.createEntityManagerFactory("test").createEntityManager() 设置它。 这与 Java EE 容器无关。

【讨论】:

以上是关于如何使用 JPA 实现测试 DAO?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 EntityManager (JPA) 在 DAO 中实现 update() 方法?

使用Spring Data JPA的Spring Boot

Spring JPA:在 CI 环境中使用多个数据库测试 DAO 层

使用 JSF、JPA 和 DAO。没有春天?

什么测试以及如何测试使用 JPA 实现的存储层

你如何为 Seam / JPA (hibernate) 创建一个 DAO 类?