1

この質問は、ここここで尋ねた質問の拡張/組み合わせです。

私の最終目標は、次のようなドメイン クラスを持つことです。

  1. プロパティを考慮して生成されるequalsおよびhashCodeメソッド@EqualsAndHashCodehasMany
  2. ドメイン クラスのプロパティのunique制約では、プロパティがhasMany考慮されます
  3. ドメイン クラスのインスタンスは、そのプロパティの 1 つが既存のインスタンスと異なる限り、一意であると見なされます。

@James Kleeh と @dmahapatro のおかげで、私は近いと思いますが、ポイント 2 と 3 が問題を引き起こしています。

testFooWithMockedBar要件をテストする最初の試みは、FooTests.groovyファイルの単体テストでした。Bar.get()そのテストで使用しようとしていますが、機能していません。への呼び出しもうまくいかなかったと思いmockForConstraintsTestsます。

私は次のテストでこの問題を修正しtestFooWithoutMockedBarたと確信していますが、次に説明するように、テストが私が思っていることを行っているかどうかはわかりません。

合格した後testFooWithoutMockedBar、アプリを開発モードで実行して、期待どおりに機能するかどうかを確認しました。残念ながら、ファイルbars内の行の属性が原因で、Grails がデータベース内にテーブルを作成できません。これが私が得るエラーです:prop1(unique: ['prop2', 'prop3', 'bars'])Foo.groovyfoo

| Error 2013-08-20 16:17:52,249 [localhost-startStop-1] ERROR hbm2ddl.SchemaExport  - Unsuccessful: create table foo (id bigint not null auto_increment, version bigint not null, prop1 varchar(255) not null, prop2 varchar(255) not null, prop3 varchar(255) not null, primary key (id), unique (foo_bars_id, prop3, prop2, prop1)) ENGINE=InnoDB
| Error 2013-08-20 16:17:52,250 [localhost-startStop-1] ERROR hbm2ddl.SchemaExport  - Key column 'foo_bars_id' doesn't exist in table
| Error 2013-08-20 16:17:52,309 [localhost-startStop-1] ERROR hbm2ddl.SchemaExport  - Unsuccessful: alter table foo_bar add index FKD76E651A96EEE146 (foo_bars_id), add constraint FKD76E651A96EEE146 foreign key (foo_bars_id) references foo (id)
| Error 2013-08-20 16:17:52,310 [localhost-startStop-1] ERROR hbm2ddl.SchemaExport  - Can't create table 'foobar.#sql-474_8c' (errno: 150)

これを修正するためのグルーヴィーな方法があるかどうかはわかりません。それを修正するために私が考えることができる唯一の方法は、カスタムバリデーターを使用することですFoo.groovy:

class Foo {

...

    boolean isUnique
    static transients = ['isUnique']

    static constraints = {
        isUnique(
            validator: { val, obj ->
                def rslt = true
                for(foo in Foo.getAll()) {
                    if (foo == obj) {
                        rslt = false
                        break
                    }
                }
                return rslt
            }
        )
        bars(nullable: false)
    }

私がやりたいことをするためのより良い方法はありますか?

フーグルービー

package foobar

@groovy.transform.EqualsAndHashCode
class Foo {

    String prop1
    String prop2
    String prop3

    Set<Bar> bars
    static hasMany = [bars: Bar]

    static constraints = {
        prop1(unique: ['prop2', 'prop3', 'bars']) // The 'bars' in this line is preventing Grails from creating the foo table in the database.
        bars(nullable: false)
    }
}

Bar.groovy

package foobar

@groovy.transform.EqualsAndHashCode
class Bar {
    String prop1
}

FooTests.groovy

package foobar

import grails.test.mixin.*
import org.junit.*

@TestFor(Foo)
@Mock(Bar)
class FooTests {

    void testFooWithMockedBar() {

        // Create existing instances to validate against
        mockForConstraintsTests(Bar, [
                new Bar(prop1: "a"),
                new Bar(prop1: "b"),
                new Bar(prop1: "c"),
                new Bar(prop1: "d")
            ]
        )
        mockForConstraintsTests(Foo, [
                new Foo(prop1: "a", prop2: "b", prop3: "c", bars: [Bar.get(1), Bar.get(2)])
            ]
        )

        // Validation should fail if all properties are null
        def foo = new Foo()
        assert !foo.validate()
        assert "nullable" == foo.errors["prop1"]
        assert "nullable" == foo.errors["prop2"]
        assert "nullable" == foo.errors["prop3"]
        assert "nullable" == foo.errors["bars"]

        // Test unique constraints
        foo = new Foo(prop1: "a", prop2: "b", prop3: "c", bars: [Bar.get(1), Bar.get(2)])

        assert !foo.validate()
        assert "unique" == foo.errors["prop1"]

        // Validation should pass with all unique, not null properties
        foo = new Foo(prop1: "a", prop2: "b", prop3: "c", bars: [Bar.get(3), Bar.get(4)])
        assert foo.validate()

        // Test equals and hashCode
        assert foo == new Foo(prop1: "a", prop2: "b", prop3: "c", bars: [Bar.get(3), Bar.get(4)])
    }

    void testFooWithoutMockedBar() {

        // Create existing instances to validate against
        def bars1 = [new Bar(prop1: "a"), new Bar(prop1: "b")]
        def bars2 = [new Bar(prop1: "c"), new Bar(prop1: "d")]
        mockForConstraintsTests(Foo, [
                new Foo(prop1: "a", prop2: "b", prop3: "c", bars: bars1)
            ]
        )

        // Validation should fail if all properties are null
        def foo = new Foo()
        assert !foo.validate()
        assert "nullable" == foo.errors["prop1"]
        assert "nullable" == foo.errors["prop2"]
        assert "nullable" == foo.errors["prop3"]
        assert "nullable" == foo.errors["bars"]

        // Test unique constraints
        foo = new Foo(prop1: "a", prop2: "b", prop3: "c", bars: bars1)

        assert !foo.validate()
        assert "unique" == foo.errors["prop1"]

        // Validation should pass
        foo = new Foo(prop1: "a", prop2: "b", prop3: "c", bars: bars2)
        assert foo.validate()

        // Test equals and hashCode
        assert foo != new Foo(prop1: "a", prop2: "b", prop3: "c", bars: bars1)
        assert foo == new Foo(prop1: "a", prop2: "b", prop3: "c", bars: bars2)
    }
}
4

1 に答える 1

0

試す

@EqualsAndHashCode(includeFields=true)

また

@EqualsAndHashCode(callSuper=true)
于 2013-08-21T09:31:00.603 に答える