集成流程测试Spring事务

时间:2019-05-13 15:39:19

标签: spring-boot integration-testing spock spring-transactions spring-test

我目前正在为Spring应用程序编写Spock集成测试。

我想使用@Stepwise来执行与数据库交互的测试,然后在第一个测试留下的数据之上进行下一个测试。

不幸的是,似乎每种测试方法都会启动一个新事务,从而清除了我需要建立的数据。 Rollback(false)不会阻止这种行为,因为整个交易都会被AFAIK丢弃。

下面是一个示例,MyUserService@Repository接口进行交互。

@Stepwise
@SpringBootTest
@TestPropertySource(locations = "classpath:application-test.properties")
class MyServiceImplIntegrationFlowSpec extends Specification {

  @Autowired
  @Subject
  MyUserService myUserService

  @Shared
  String userId

  void "create user"() {

    when:
    userId = myUserService.createUser()

    then:
    userId
  }

  void "change user permission"() {

    when:
    myUserService.changePermission(userId, "read")

    then:
    myUserService.fetchPermission() == "read"
  }
}

如何结合数据库操作重复使用由@Stepwise常见的由先前测试方法创建的数据?

1 个答案:

答案 0 :(得分:1)

Spring Test框架默认回滚每个测试方法的数据。您可以通过将@Commit批注添加到要保留更改在数据库中的每个测试方法中来更改此默认行为。如果整个测试套件都应将数据提交到数据库,我想您也可以在类级别上添加@Commit批注。

请参见参考文献https://docs.spring.io/spring/docs/current/spring-framework-reference/testing.html#testing-tx

它说:

  

访问真实数据库的测试中的一个常见问题是它们的影响   在持久性存储的状态上。即使使用开发   数据库,状态更改可能会影响以后的测试。还有很多   操作,例如插入或修改持久数据,不能   在交易之外执行(或验证)。

并继续描述

  

TestContext框架解决了此问题。 默认情况下,   框架会为每个测试创建并回滚交易。您可以   编写可以假定存在事务的代码。如果你打电话   测试中的事务代理对象,它们的行为正确,   根据其配置的事务语义。另外,如果   测试方法在运行时删除所选表的内容   在为测试管理的交易中,交易进行   默认情况下返回,并且数据库返回到之前的状态   执行测试。为测试提供交易支持   使用测试中定义的PlatformTransactionManager bean   应用程序上下文。

     

如果您要提交事务(不寻常,但偶尔有用   当您希望特定测试填充或修改数据库时,   您可以告诉TestContext框架使事务   通过使用 @Commit 注释来提交而不是回滚。

您的测试用例可能看起来像

@Stepwise
@SpringBootTest
@TestPropertySource(locations = "classpath:application-test.properties")
@Commit // if you want all test methods to commit to the database
class MyServiceImplIntegrationFlowSpec extends Specification {

  @Autowired
  @Subject
  MyUserService myUserService

  @Shared
  String userId

  @Commit // if a single test needs to commit to the database
  void "create user"() {

    when:
    userId = myUserService.createUser()

    then:
    userId
  }

  void "change user permission"() {

    when:
    myUserService.changePermission(userId, "read")

    then:
    myUserService.fetchPermission() == "read"
  }
}
相关问题