java - 在 cucumber-jvm 测试中回滚事务

标签 java spring hibernate transactions cucumber-jvm

我目前正在使用 Spring 开发 REST Web 服务,使用 Hibernate 作为 ORM 并使用 cucumber 编写验收测试。

为了能够在场景之间回滚事务,我有以下代码,它在每个场景之前创建一个事务并在其之后回滚。

package com.orange.cainet.cucumber;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.web.WebAppConfiguration;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.DefaultTransactionDefinition;
import cucumber.api.java.After;
import cucumber.api.java.Before;

@WebAppConfiguration
@ContextConfiguration("classpath:applicationContext.xml")
public class RollbackTransactionsBetweenScenarios {

    @Autowired
    PlatformTransactionManager transactionManager;

    TransactionStatus transaction;

    @Before
    public void beforeScenario(){       
        transaction = transactionManager.getTransaction(new DefaultTransactionDefinition());
    }

    @After
    public void afterScenario(){
        transactionManager.rollback(transaction);
    }
}

在步骤定义类中,我使用实体的 Autowiring CrudRepository 来创建 Give 语句中的内容并断言 then 语句中的内容。

我使用 MockMvc 来模拟应用程序上下文,并使用 (post、get...) 发送虚假请求并将 ResultActions 保留为字段以在断言中使用它。

直到最近,这对我来说都很好,当使用 @Column(unique=true) 来防止实体中的字段之一重复,并使用 DataIntegrityViolationException 来知道我何时要删除该实体时,问题就开始了保存有重复的字段

try{
    newUser = userRespoitory.save(newUser);         
}
catch(DataIntegrityViolationException exception){
    throw new UserNameAlreadyExistsException();
}  

问题是,抛出 DataIntegrityViolationException 后,每当我在任何 cucumber 步骤定义函数中使用 UserRepository.findOne() 时,测试都会引发错误

org.hibernate.AssertionFailure: null id in com.komalo.domain.User entry (don't flush the Session after an exception occurs)

我明白这是因为我在每个场景之前创建的事务,如果我在使用 UserRepository 之前回滚该事务,它就会正常工作。

所以我的问题是:

1) 这是编写测试的正确方法吗? ,因为我使用的是 UserRepository,这是我正在进行验收测试的一部分,但我认为由于它是由 Spring Data 实现的,所以应该没问题。

2) 即使在抛出异常之后,是否有办法继续使用事务?

3)这可以通过不依赖 DataIntegrityViolationException 轻松解决,而是通过在接口(interface)中创建一个额外的方法(如 UserRepository.findOneByUsername() )并使用它来手动检查,但这不是正在执行的额外 select 语句吗? ?

最佳答案

好吧,我没有明确的答案,但您最好清理并重新插入数据,或者在代码中添加一些逻辑,例如:

if(userRepositry.findOne(newUser.getName())==null)
newUser = userRespoitory.save(newUser);         

但我认为这不是使用 BDD 的正确方法。

您需要将数据创建与存储库和生产代码状态分开,而且您的测试必须彼此独立,因此 clean->run 对我来说看起来不错。

关于java - 在 cucumber-jvm 测试中回滚事务,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26077921/

相关文章:

java - 如何使用 AJAX 将数组从 Servlet 发送到 Javascript?

mysql - 是什么导致 "ARJUNA012117: TransactionReaper::check timeout for TX 0:ffff0a400e22:2251d537:519c37fa:35d4 in state RUN"

java - HQL递归,我该怎么做?

java - 如何在 Spring JPA 中为审计字段 @CreatedDate、@LastModifiedDate 保存 UTC 格式的时间戳

java - 通过java配置文件中的名称获取Bean

java - 以编程方式创建架构时出现未知数据库异常?

java - 使用 Eclipse 的 xml 智能感知?

java - 是否可以在 Android 中使用 YouTube API 来显示 360° 视频?

java - 我如何解密和加密 Java 程序的 Joomla 用户密码?

java - 删除 H2 数据而不删除表