首页 > 解决方案 > 实体层的 SpringBoot、JPA 和 Hibernate 单元测试

问题描述

我正在使用 SpringBoot、JPA 和 Hibernate 实现一个项目。

我使用 JPA 存储库实现了 DB 实体层。

我有兴趣了解为这一层编写单元测试的最佳实践。

我试图了解这些最佳实践,同时,我尝试编写测试的第一个示例:

@ActiveProfiles("test")
@DisplayName("Test Item JPA Entity")
@DataJpaTest
@AutoConfigureTestDatabase( replace = AutoConfigureTestDatabase.Replace.NONE )
public class ItemEntityTest {

    @Autowired
    MyEntityRepository repo;

    @Test
    @Transactional
    public void testEntityCreation() {

        Entity e = new Entity();
        e.setMyField1("A");
        e.setMyField1("A");
        //e.setMandatoryField("C")

        repo.save(e);

    }
}

不幸的是,在这种情况下,我注意到没有应用字段验证(@NotNull 或@NotEmpty,或@Column(nullable = false)等......如果我尝试将实体保存到我的应用程序中,验证工作正常。 .. 引发异常)。为什么?

还有一些“自动字段”(例如创建时间和最后修改时间)没有填写。

这是正确的路径吗?何来测试我的实体定义?

标签: javaspring-boothibernateunit-testingjpa

解决方案


正如那个答案中提到的,问题在于@DataJpaTestspring将使用TestEntityManager并且事务注释将覆盖spring boot的默认自动提交和回滚行为。

因此,您的测试方法将通过并假设 hibernate 是此处使用的 ORM,当最终进行刷新时,将触发 hibernate 的 pre-insert 事件并应用验证,但您的测试用例将在此之前通过,因此它将产生误报(如 spring 文档中使用的术语)

解决方案:您需要在测试中注入实体管理器并手动刷新它,以便在测试完成之前触发休眠预插入事件。

@ActiveProfiles("test")
@DisplayName("Test Item JPA Entity")
@DataJpaTest
@AutoConfigureTestDatabase( replace = AutoConfigureTestDatabase.Replace.NONE )
public class ItemEntityTest {

    @Autowired
    MyEntityRepository repo;

    @Autowired
    private TestEntityManager em;

    @Test
    @Transactional
    public void testEntityCreation() {

        Entity e = new Entity();
        e.setMyField1("A");
        e.setMyField1("A");
        //e.setMandatoryField("C")

        repo.save(e);
        
        em.flush();
    }
}

这必须触发您对所应用实体的验证,这在spring framework docs中有记录。 请注意,文档是关于 spring 框架并使用会话工厂,但概念是相同的

您也可以查看spring boot docs,它指向 spring 框架文档以了解此行为。


推荐阅读