2012年1月7日土曜日

Grails2.0のDomainのUnit Testハマリどころ

今日はGrailsのDomainテストのハマリどころについてのメモです。
と言っても、ひとつしか書いていませんが…

ConstraintsのValidationテスト


前回の記事ではValidationのテストについて少し取り扱っています。

Book.groovy

class Book {

    String name

    String author

    int price

    static constraints = {
        name (blank: false)
        author (blank: false)
        price (min: 0)
    }
}


BookTests.groovy

@Test
    void validation() {
        def book = new Book(name: '吾輩は猫である', price: -1)
        assert book.validate() == false
    }


このテストで分かるのはこのままでは登録できないということです。

ただ、残念なことに何が悪くてValidationで引っかかったのかがわかりません。

この際に役立つのがPOGOに自動的に付与されるerrorsというメンバーです。

くせもののerrors


このerrorsにはvalidate()でチェックされたエラーのスナップショットが格納されています。

上記のコードの例では、Bookクラスには著者の情報が未設定であり、不適切な価格情報が設定されているという状態です。

したがって、errorsにはauthorpriceというメンバーが存在します、いや、するはずです。

では、本当にpriceで引っかかっているのか確認するテストを書きます。


@Test
    void validation() {
        def book = new Book(name: '吾輩は猫である', price: -1)
        assert book.validate() == false
        assert book.errors['price'] == 'min'
    }


このテストはvalidate()でチェックされたエラーのうち、priceに対するエラーはminであることをテストします。

おもむろに実行します。

実行結果(一部略)


| Failure:  validateQuantity(grailsshop.Book)
|  Assertion failed:

assert book.errors['price'] == 'min'
       |   |      |        |
       |   |      |        false
       |   |      Field error in object 'grailsshop.Book' on field 'price': rejected value [0];
       |   Field error in object 'grailsshop.Book' on field 'price': rejected value [0];
       grailsshop.Book: null


実際はもっと長ったらしいエラーメッセージが出ますが、Field errorの部分の内容を見るかぎりではこのテストは通ってもよさそうなものなのですが、ダメなんですね。

書き方間違えたのかと思って、公式サイトを確認しましたが、合っているようです。

mockForConstraints


そんなこんなで、混乱していたところ、Grailsの第一人者であられる@tyamaさんからアドバイスをいただきました。


ふむ、mockForConstraints(Class<T>)を使えばよいとな。

というわけで、おもむろに入れてテストを通してみる。


@Test
    void validation() {
        mockForConstraintsTests(Book)
        def book = new Book(name: '吾輩は猫である', price: -1)
        assert book.validate() == false
        assert book.errors['price'] == 'min'
    }


そして、テスト実行。


grails> test-app grailsshop.Book
| Completed 1 unit tests, 0 failed in 361ms
| Tests PASSED - view reports in target/test-reports


おお、通った。

結論


とりあえず、Grails2.0constraintsValidationテストをする場合は、黙ってmockForConstraintsTestsを使っとけという話ですな。


0 件のコメント:

コメントを投稿