更新时未保存Grails布尔字段

时间:2015-02-21 08:39:10

标签: grails gorm

我有一个有两个A&类的模型。 B,它们都有一个“boolean lastVersion”字段

类“A”具有关联“B b”,而在A.beforeInsert / beforeUpdate中,A.lastVersion的值被复制到B.lastVersion。

A.lastVersion和B.lastVersion的默认值为true。当我将.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
    }
}

1 个答案:

答案 0 :(得分:0)

我已经从testbools237文件中添加了您的源代码,以便其他人更轻松地查看源代码,但我没有足够的声誉可以批准编辑,所以也许是原始海报或其他人可以查看和更新​​。

您在单元测试中创建了一个新的CompositionIndex,但它没有被嘲笑,所以我认为您的测试不会按预期工作。我会尝试通过以下方式创建一个协作者:

@Mock(CompositionIndex)

在此注释下:

@TestFor(Version)

详细信息:http://grails.github.io/grails-doc/2.4.3/guide/testing.html#unitTesting - 请参阅“测试混合基础知识”一节。

编辑:

除了我的上一次,您还需要确保在进行测试断言之前,您正在编辑的域模型实际上已保存到数据库中。在域对象上调用save()实际上并不意味着保存了对象,它只是意味着您已经表示要保存它。 Peter Ledbrook很好地解释了here

如果您在失败的测试断言之前更改了保存:

if (!vget.save()) println vget.errors

到此:

if (!vget.save(flush: true)) println vget.errors

然后你的测试应该按预期运行(你的失败测试现在无论如何都会在我的机器上传递)。