我试图在黄瓜测试的背景阶段使用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界面来更改用户的密码。一旦该场景运行, 对于该功能中的所有后续方案,背景将因上述错误而失败。
所有不改变任何用户属性的测试都会成功。如何避免这种乐观锁定错误?
谢谢!
答案 0 :(得分:0)
您不应该有查询,特别是在步骤中编写查询。将该代码移动到服务中以获得正确的事务/提交处理。
对于普通的Grails也是如此,但根据我的经验,它并没有直接显示出来。
我喜欢从@Before钩子调用清理。这样可以保留那些技术性的东西,比如数据库被重置'在场景之外。
请注意,自grails 2.3以来,不再为新代码直接调用grails中的grails内容。当前样式仍将在grails非分叉模式下工作,但它永远不会在分叉模式下工作。请参阅此article。