spring - JUnit、JPA 和 Spring : How to ensure that unit tests leave database clean on completion

标签 spring jpa junit

我正在尝试使用 SpringJunit4ClassRunner 通过使用 @Transactional 注释来测试我的 DAO 类,而不会在我完成后留下数据。我的 DAO 类包含(精简):

@Repository
public class IdsFunctionJpaController {

  @PersistenceContext
  EntityManager em;

  public void save(IdsFunction function) {
    if (function.getId() == 0) {
      create(function);
    } else {
      update(function);
    }
  }

  @Transactional
  private void create(IdsFunction idsFunction) {
    try {
      em.persist(idsFunction);
    }
    catch (Exception e) {
      System.out.println(e);
    } finally {
      em.close();
    }
  }

  @Transactional
  private void update(IdsFunction function) {
    try {
      em.merge(function);
    } finally {
      em.close();
    }
  } 
}

我的起始 JUnit 测试用例是

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations={"/applicationContext.xml"} )
public class IdsFunctionJpaControllerTest {

  @Autowired
  IdsFunctionJpaController dao;

  @Test
  @Transactional
  public void addFunction() {
    IdsFunction function = new IdsFunction();
    function.setDescription("Test Function Description");
    dao.save(function);
    assertTrue(function.getId() != 0);
  }
}

我在这里要做的只是测试实体是否已创建,但此测试失败了。如果我删除 @Transactional 注释,则测试通过,但测试实体保留在数据库中。我做错了什么?

问候

最佳答案

代理机制

你在用你的头撞 JDK 代理。

您的 dao.save() 方法是非事务性的,它会尝试调用事务性方法 create()update()。但是事务性的事情发生在类外的 JDK 代理中,而保存方法已经在类中。

参见 this previous answer of mine供引用。

解决方案:

  • 使您的save() 方法具有事务性
  • (更好)根本不要让您的 DAO 具有事务性。事务属于服务层,而不是 DAO 层。

引用:


更新:我被 Dao 方法上令人困惑的 @Transactional 注释误导了。你应该删除它们,它们什么都不做,还会让人感到困惑。

正如您在我上面发布的链接中所读到的,@Transactional 注释仅在它们出现在将从 Spring bean 外部调用的公共(public)方法上时才有效(因此您不能类中的一个方法委托(delegate)给同一类的一个或多个代理方法)。


交易测试

Spring 为事务测试提供了特殊的支持类,如 9.3.5.4 Transaction management 中所述。 .如果你让你的测试类从 AbstractTransactionalJUnit4SpringContextTests 扩展每次测试后都会自动回滚事务。在大多数情况下,这正是您所需要的。

关于spring - JUnit、JPA 和 Spring : How to ensure that unit tests leave database clean on completion,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4919904/

相关文章:

java - 如何使用 mockito 测试运行异步线程的方法

java - Spring Boot是否自动解析javax和hibernate验证注解中的消息键

java - @NamedStoredProcedureQuery 不适用于 Hibernate 5.1.x 和 JPA2.1

java - 如何使用具有 Autowiring 依赖项的 init 方法?

java - 如何用连接列指定外键?

tomcat - 使用 EclipseLink 配置连接池

java - 使用@Async 方法的 JUnit 回滚事务

java - @TestPropertySource 不适用于 Spring 1.2.6 中使用 AnnotationConfigContextLoader 的 JUnit 测试

java - Spring Boot 与 GraphQL - 架构问题

java - Spring 中接口(interface)的依赖注入(inject)