1

統合テストでGORMに楽観的ロックエラーをスローさせようとしています。複数のスレッドに頼らずに同時更新エラーをテストすることはできないと前に言われましたが、それでも私のテスト ケースの動作は驚くべきものでした。

void testOptimisticLocking() {

    new Widget(foo:"bar").save(flush:true)

    // Get the widget and change a property
    def widget = Widget.findByFoo("bar")
    assertNotNull widget
    widget.foo = "baz"
    def widgetVersion = widget.version
    println "widget: $widgetVersion"   // >>>  widget: 0

    // Discard the widget without saving; Hibernate now knows nothing about it
    widget.discard()

    // Get a different instance of the same widget from the database,
    // with the old value for foo
    def sameWidget = Widget.findByFoo("bar")
    assertNotNull sameWidget
    assertFalse System.identityHashCode(sameWidget) == System.identityHashCode(widget)

    // Change the foo property and save
    sameWidget.foo = "bat"
    sameWidget.save(flush:true)

    // Check the version has incremented
    println "sameWidget: $sameWidget.version"         // >>>  sameWidget: 1
    assertTrue widgetVersion < sameWidget.version

    // Check the database hold the "bat" widget
    sameWidget.discard()
    assertEquals 0, Widget.countByFoo("bar")
    assertEquals 1, Widget.countByFoo("bat")

    // Reattach the original widget and try to save it
    assertFalse widget.isAttached()
    widget.attach()
    println "widget: $widget.version"            // >>>  widget: 0
    assertEquals widgetVersion, widget.version
    assertEquals "baz", widget.foo

    // TEST FAILS HERE
    // No error is thrown, and the update fails silently!
    shouldFail(org.hibernate.StaleStateException) {
        assertTrue widget.validate()
        widget.save(flush:true)
        println widget.foo              // >>>  baz
        widget.discard()
        println "baz: " + Widget.countByFoo("baz")    // >>>  baz: 0
        println "bat: " + Widget.countByFoo("bat")    // >>>  bat: 1
    }



}

Widget の再アタッチされたインスタンスはデータベースに永続化されませんが、例外はスローされません!

私のテストケースはかなり不自然ですが、それでも結果には驚かされます。

誰でもこれを説明できますか?

4

0 に答える 0