我有一个带有两个类A和B的模型,它们两个都有一个“boolean lastVersion”字段。
类“A”具有关联“B b”,并且在A.beforeInsert / beforeUpdate上,将A.lastVersion的值复制到B.lastVersion中。
A.lastVersion和B.lastVersion的默认值为true。当我将a.lastVersion更改为 false 并执行a.save()时,lastVersion均未设置为false。如果我做a.save(flush:true),只有a.b.lastVersion被保存为false;
对这里的问题有什么想法吗?
我已经使用H2数据库在v2.1.0和v2.3.7上对此进行了测试。编辑:在MySQL上测试,得到了相同的行为。
Here,您可以找到两个示例应用程序(代码也包括在下面)。运行应用程序并检查H2 dbconsole时,会发生奇怪的行为。有一个名为VersionTests的单元测试,该单元测试也获得了行为IMO的不一致。
package testbools
class Version {
static constraints = {
ci (nullable: true)
}
boolean lastVersion = true
CompositionIndex ci
def beforeInsert() {
this.ci.lastVersion = this.lastVersion
}
def beforeUpdate() {
this.ci.lastVersion = this.lastVersion
}
}
package testbools
class CompositionIndex {
static constraints = {
}
boolean lastVersion = true
static belongsTo = [Version]
}
和测试:
package testbools
import grails.test.mixin.*
import org.junit.*
/**
* See the API for {@link grails.test.mixin.domain.DomainClassUnitTestMixin} for usage instructions
*/
@TestFor(Version)
class VersionTests {
void testSomething() {
def v = new Version(ci: new CompositionIndex())
if (!v.save()) println v.errors
def vget = Version.get(1)
assert vget.lastVersion
assert vget.ci.lastVersion
// change value
vget.lastVersion = false
if (!vget.save()) println vget.errors
// value has been changed?
assert !vget.lastVersion
assert !vget.ci.lastVersion
// value has been stored?
def vget2 = Version.get(1)
assert !vget2.lastVersion
assert !vget2.ci.lastVersion
}
}
最佳答案
我已经从testbools237文件中添加了您的源代码,以使其他人可以更轻松地查看源代码,但是我没有足够的声誉来批准编辑,因此也许原始的发帖人或其他人都可以查看并更新。
您正在单元测试中创建一个新的CompositionIndex,但是还没有被模拟出来,因此我认为您的测试不会按预期工作。我会尝试通过以下方式创建协作者:
@Mock(CompositionIndex)
在此注释下:
@TestFor(Version)
此处的详细信息:http://grails.github.io/grails-doc/2.4.3/guide/testing.html#unitTesting-请参阅标题为“Test Mixin基础知识”的部分。
编辑:
在我上次讲完之后,您还需要确保在进行测试断言之前,您正在编辑的域模型已实际保存到数据库中。在域对象上调用save()实际上并不意味着该对象已保存,而只是意味着您已经说过要保存它。彼得·莱德布鲁克(Peter Ledbrook)很好地解释了here。
如果您在失败的测试断言之前从以下位置更改保存:
if (!vget.save()) println vget.errors
对此:
if (!vget.save(flush: true)) println vget.errors
那么您的测试应该可以达到预期的效果(失败的测试现在无论如何都会通过我的计算机)。