使用内存中的H2数据库在Grails 2.4.4中执行REST API功能测试时的表锁定超时

使用内存中的H2数据库在Grails 2.4.4中执行REST API功能测试时的表锁定超时,rest,grails,testing,locking,functional-testing,Rest,Grails,Testing,Locking,Functional Testing,我正在尝试使用和插件为我的RESTAPI创建一组功能测试 我的H2 DB连接字符串如下所示: url = "jdbc:h2:mem:testDb:MVCC=true;LOCK_TIMEOUT=5000" 首先,我初始化h2数据库,在setup()方法中引入一些记录。 一切正常 def setup() { // Clean elasticsearch index elasticSearchService.reinitialiseIndex() // Initialize

我正在尝试使用和插件为我的RESTAPI创建一组功能测试

我的H2 DB连接字符串如下所示:

url = "jdbc:h2:mem:testDb:MVCC=true;LOCK_TIMEOUT=5000"
首先,我初始化h2数据库,在setup()方法中引入一些记录。 一切正常

def setup() {
    // Clean elasticsearch index
    elasticSearchService.reinitialiseIndex()

    // Initialize the DB
    // 1st question
    questionService.createQuestionFromOccurrence(
            '181718e6-fd3b-4a1b-8b40-3f83fd2965e5',
            QuestionType.IDENTIFICATION,
            ['kangaroo', 'grey'],
            userMick,
            '1st question 1st comment'
    )
}
但当我执行测试和POST请求时:

RestResponse response = rest.post("http://localhost:8080/${grailsApplication.metadata.'app.name'}/ws/question") {
    json([
            source      : 'biocache',
            occurrenceId: 'f6f8a9b8-4d52-49c3-9352-155f154fc96c',
            userId      : userKeef.alaUserId,
            tags        : 'octopus, orange',
            comment     : 'whatever'
    ])
}
该进程在第一个DB操作中失败,在本例中,该操作是
get()
,但出现以下异常:

ERROR errors.GrailsExceptionResolver  - JdbcSQLException occurred when processing request: [POST] /taxon-overflow/ws/question
Timeout trying to lock table "QUESTION"; SQL statement:

看起来Grails测试中的所有DB操作都是在每次测试后回滚的事务中执行的。显然,它还锁定了数据库,因为REST请求将在测试的单独线程中执行,这意味着它无法访问数据库。即使未锁定,进程也不会看到数据,因为数据从未提交

实现此功能的一种方法是通过向测试中添加属性使测试“非事务性”:

class RestAPISpec extends IntegrationSpec {
    static transactional = false
    ...
}
这种方法的一个问题是,在每次测试之后,必须手动
cleanup()
数据库。以下是我发现的最简单的方法:

def grailsApplication
def sessionFactory
...
def cleanup() {
    (grailsApplication.getArtefacts("Domain") as List).each {
        it.newInstance().list()*.delete()
    }
    sessionFactory.currentSession.flush()
    sessionFactory.currentSession.clear()

    sourceService.init()
}
另一种方法是通过在集成测试中测试控制器来测试RESTAPI,这也有点麻烦,而且它不是真正的web服务的e2e测试。另一方面,它的执行速度比功能测试快一点