Unit testing Grails2.4.5控制器单元测试验证事务已回滚

Unit testing Grails2.4.5控制器单元测试验证事务已回滚,unit-testing,grails,Unit Testing,Grails,这是一个简单的控制器 class UserController { @Transactional def update() { try { .... throw new Exception("test transaction rollback") ... } catch( e ) { transactionStatus.setRollbackOnly() respond "{ "s

这是一个简单的控制器

class UserController {
   @Transactional
   def update() {
      try {
        ....
        throw new Exception("test transaction rollback")
        ...
      } catch( e ) {
        transactionStatus.setRollbackOnly()
        respond "{ "status":"error" }"
      }
   }
}
这是一个单元测试规范

@TestFor(UserController)
class UserControllerSpec extends Specification {
   when:''
   controller.update()

   then:'verify that transaction has been rolled back'
   // it fails with missing property, whats the best way to check that it was rolled back ?
   controller.transactionManager.transactionRolledBack == true
}
测试事务是否已回滚的最佳方法是什么

@BurtBeckwith suggestion之后尝试了一个集成规范

//域用户.groovy

class User { String firstName; String lastName }
//UserController.groovy

  class UserController {
    static responseFormats = ['json', 'xml']
    static allowedMethods = [update: 'PUT']
    @Transactional
    def update( UserCommand cmd ) {
       User m = User.get(id)
       m.firstName=cmd.firstName
       m.lastName=cmd.lastName
       m.save(failOnError:true,flush:true)
       transactionStatus.setRollbackOnly()
    }
  }
  class UserCommand { Long id; String firstName; String lastName }
//IntegrationSpec UserControllerIntegrationSpec.groovy

import grails.test.spock.IntegrationSpec
class UserControllerIntegrationSpec extends IntegrationSpec {
   def controller
   def sessionFactory

   def setup() {
     controller = new UserController()
   }

   void "test transaction rollback"() {
      given:'a user'
      User u = new User(firstName:'oldFirstName',lastName:'oldLastName')
      u.save(flush:true,failOnError:true)

      controller.request.method='PUT'
      controller.request.contentType = "application/json"
      controller.request.content =   '{"id":u.id,"firstName":"newFirstName","lastName":"newLastName"}'.getBytes()

      when:'an update that rollsback is called'
      controller.update()
      // clear so that we do not get data from cache.
      sessionFactory.currentSession.flush()
      sessionFactory.currentSession.clear()

      then:'we should still see old data'
      User u2 = User.get(u.id)
      // The following fails, u.firstName has 'newFirstName' which is wrong on rollback
      u2.firstName == 'oldFirstName'
      u2.lastName == 'oldLastName'

   }
}
//DataSource.groovy

    test {
        dataSource {
            url = "jdbc:mysql://localhost/starter_app_test"
            driverClassName = "com.mysql.jdbc.Driver"
            pooled = true
            properties {
                ...
                defaultAutoCommit=false
            }
        }
    }

您知道为什么即使在回滚时,集成测试数据也会持久化吗?

至少您需要使用集成测试,因为单元测试中使用的GORM不使用数据库,只使用由ConcurrentHashMap支持的内存存储。感谢@BurtBeckwith创建了一个集成规范,有趣的是,即使在调用“setRollbackOnly()”之后,数据似乎仍然存在