黄瓜的乐观锁定失败测试数据负载和grails 2.3.8

时间:2014-05-02 21:21:02

标签: hibernate grails locking cucumber gorm

我试图在黄瓜测试的背景阶段使用GORM删除和创建数据。 当我尝试删除在上一个场景中更改的背景中的对象时, 我看起来像一个乐观的锁定违规。我使用grails 2.3.8,和hibernate 3.6.10.13,以及黄瓜0.10.0。我用mysql或H2数据库得到了同样的错误。

这是错误消息:

    | Error 2014-05-02 14:24:09,092 [main] ERROR events.PatchedDefaultFlushEventListener  - Could not synchronize database state with session
    Message: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect): [com.example.angugrails.auth.User#170]
    Line | Method
    ->>  13 | doCall        in steps.DataSteps$_run_closure1_closure3
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    |    11 | doCall        in steps.DataSteps$_run_closure1
    |   146 | invoke . . .  in cucumber.runtime.groovy.GroovyBackend
    |    67 | call          in cucumber.runtime.groovy.GroovyStepDefinition$1
    |    12 | timeout . . . in cucumber.runtime.Timeout
    |    64 | execute       in cucumber.runtime.groovy.GroovyStepDefinition
    |    38 | runStep . . . in cucumber.runtime.StepDefinitionMatch
    |   289 | runStep       in cucumber.runtime.Runtime
    |    44 | runStep . . . in cucumber.runtime.model.StepContainer
    |    39 | runSteps      in     ''
    |    49 | runBackground in cucumber.runtime.model.CucumberScenario
    |    38 | run           in     ''
    |   116 | run . . . . . in cucumber.runtime.model.CucumberFeature
    |    59 | doCall        in grails.plugin.cucumber.Cucumber$_run_closure2
    |    58 | run . . . . . in grails.plugin.cucumber.Cucumber
    |   121 | runFeatures   in grails.plugin.cucumber.CucumberTestType
    |    57 | doRun . . . . in     ''
    |   102 | doCall        in _GrailsTest_groovy$_run_closure1
    |    32 | doCall . . .  in TestApp$_run_closure1
    ^   120 | main          in com.intellij.rt.execution.application.AppMain

这是来自DataSource.groovy的hibernate配置,我试图禁用second_level_cache,因为缓存黄瓜测试中检索到的对象可能会导致这个 问题:

hibernate {
    cache.use_second_level_cache = false
    cache.use_query_cache = false
    cache.region.factory_class = 'net.sf.ehcache.hibernate.EhCacheRegionFactory' // Hibernate 3
//    cache.region.factory_class = 'org.hibernate.cache.ehcache.EhCacheRegionFactory' // Hibernate 4
    singleSession = true // configure OSIV singleSession mode
}

功能文件的背景如下所示:

Feature: User Profile
  Background:
    Given the db is reset
    Given the db is loaded with new user. username: "user1" email: "testuser1@example.com" 
    password: "testpassword1"

数据库黄瓜步骤函数如下所示:

Given(~'^the db is reset') { ->
    User.findAll().each {
        it.delete(flush: true)
    }
 }

When(~'^the db is loaded with new user. username: "([^"]*)" email: "([^"]*)" password: "([^"]*)"$') {
    String username, String email, String password ->
        def user = new User(username: username, email: email, password: password, enabled: true, accountLocked: false)
        if (!user.validate()) {
            throw new Exception("unexpected error.")
        } else {
            user.save(flush: true)
            def debug = User.findByUsername("user1")
            debug.username
        }
}

我正在运行的方案使用webdriver和Web界面来更改用户的密码。一旦该场景运行, 对于该功能中的所有后续方案,背景将因上述错误而失败。

所有不改变任何用户属性的测试都会成功。如何避免这种乐观锁定错误?

谢谢!

1 个答案:

答案 0 :(得分:0)

您不应该有查询,特别是在步骤中编写查询。将该代码移动到服务中以获得正确的事务/提交处理。

对于普通的Grails也是如此,但根据我的经验,它并没有直接显示出来。

我喜欢从@Before钩子调用清理。这样可以保留那些技术性的东西,比如数据库被重置'在场景之外。

请注意,自grails 2.3以来,不再为新代码直接调用grails中的grails内容。当前样式仍将在grails非分叉模式下工作,但它永远不会在分叉模式下工作。请参阅此article