7

バージョン 2.3.1 の grails アプリケーションと次の構成がありますBuildConfig.groovy

   dependencies {
        ...
        ..
        .
        test "org.spockframework:spock-grails-support:0.7-groovy-2.0"
    }
    plugins {
        test(":spock:0.7") {
            exclude "spock-grails-support"
        }

次のドメイン クラスがあります。

class Draft {
    def grailsApplication

    String name
    String subject
    String content

    static constraints = {
        name unique: true, blank: false
        subject blank: false
    }

    static mapping = {
        content type: 'text'
    }
}

私はこの投稿を見つけましたGrails 2.x & Spock 0.7を使用したドメイン制約のテスト では、ドメイン クラスの制約をテストするための興味深いアプローチを使用しています。

スポックテストがあります:

import spock.lang.Specification

abstract class ConstraintUnitSpec extends Specification {

    String getLongString(Integer length) {
        'a' * length
    }

    String getEmail(Boolean valid) {
        valid ? "dexter@miamipd.gov" : "dexterm@m"
    }

    String getUrl(Boolean valid) {
        valid ? "http://www.google.com" : "http:/ww.helloworld.com"
    }

    String getCreditCard(Boolean valid) {
        valid ? "4111111111111111" : "41014"
    }

    void validateConstraints(obj, field, error) {
        println "Draft name: " + obj.name 
        def validated = obj.validate()
        if (error && error != 'valid') {
            assert !validated
            assert obj.errors[field]
            assert error == obj.errors[field]
        } else {
            assert !obj.errors[field]
        }
    }
}

import grails.test.mixin.TestFor
import spock.lang.Unroll

@TestFor(Draft)
class DraftSpec extends ConstraintUnitSpec {
     def setup() {
        mockForConstraintsTests(Draft, [new Draft(name: 'unique')])
     }

     @Unroll("test draft all constraints #field is #error")
     def "test draft all constraints"() {
          when:
          def obj = new Draft("$field": val)

          then:
          validateConstraints(obj, field, error)

          where:
          error                  | field        | val
          'nullable'             | 'name'       | null
          'nullable'             | 'subject'    | null
          'nullable'             | 'content'    | null
          'unique'               | 'name'       | 'unique'
          'valid'                | 'name'       | 'valid name'
          'valid'                | 'subject'    | 'valid subject'
          'blank'                | 'name'       | ''
          'blank'                | 'subject'    | ''
   }
}

テストは両方のblank制約で失敗します:

Draft name: null
| Failure:  test draft all constraints subject is blank(DraftSpec)
|  Condition not satisfied:

error == obj.errors[field]
|     |  |   |     ||
blank |  |   |     |subject
      |  |   |     nullable
      |  |   org.codehaus.groovy.grails.plugins.testing.GrailsMockErrors: 3 errors
      |  |   Field error in object 'Draft' on field 'name': rejected value [null]; codes [Draft.name.nullable.error.Draft.name,Draft.name.nullable.error.name,Draft.name.nullable.error.java.lang.String,Draft.name.nullable.error,draft.name.nullable.error.Draft.name,draft.name.nullable.error.name,draft.name.nullable.error.java.lang.String,draft.name.nullable.error,Draft.name.nullable.Draft.name,Draft.name.nullable.name,Draft.name.nullable.java.lang.String,Draft.name.nullable,draft.name.nullable.Draft.name,draft.name.nullable.name,draft.name.nullable.java.lang.String,draft.name.nullable,nullable.Draft.name,nullable.name,nullable.java.lang.String,nullable]; arguments [name,class Draft]; default message [Property [{0}] of class [{1}] cannot be null]
      |  |   Field error in object 'Draft' on field 'subject': rejected value [null]; codes [Draft.subject.nullable.error.Draft.subject,Draft.subject.nullable.error.subject,Draft.subject.nullable.error.java.lang.String,Draft.subject.nullable.error,draft.subject.nullable.error.Draft.subject,draft.subject.nullable.error.subject,draft.subject.nullable.error.java.lang.String,draft.subject.nullable.error,Draft.subject.nullable.Draft.subject,Draft.subject.nullable.subject,Draft.subject.nullable.java.lang.String,Draft.subject.nullable,draft.subject.nullable.Draft.subject,draft.subject.nullable.subject,draft.subject.nullable.java.lang.String,draft.subject.nullable,nullable.Draft.subject,nullable.subject,nullable.java.lang.String,nullable]; arguments [subject,class Draft]; default message [Property [{0}] of class [{1}] cannot be null]
      |  |   Field error in object 'Draft' on field 'content': rejected value [null]; codes [Draft.content.nullable.error.Draft.content,Draft.content.nullable.error.content,Draft.content.nullable.error.java.lang.String,Draft.content.nullable.error,draft.content.nullable.error.Draft.content,draft.content.nullable.error.content,draft.content.nullable.error.java.lang.String,draft.content.nullable.error,Draft.content.nullable.Draft.content,Draft.content.nullable.content,Draft.content.nullable.java.lang.String,Draft.content.nullable,draft.content.nullable.Draft.content,draft.content.nullable.content,draft.content.nullable.java.lang.String,draft.content.nullable,nullable.Draft.content,nullable.content,nullable.java.lang.String,nullable]; arguments [content,class Draft]; default message [Property [{0}] of class [{1}] cannot be null]
      |  Draft : (unsaved)
      false
      6 differences (25% similarity)
      (b-)l(-)a(nk-)
      (nu)l(l)a(ble)

    at ConstraintUnitSpec.validateConstraints(ConstraintUnitSpec.groovy:29)
    at DraftSpec.test draft all constraints(DraftSpec.groovy:18)
| Completed 8 spock tests, 2 failed in 0m 6s
| Tests FAILED  - view reports in /Users/sdelamo/Documents/Developer/bitbucket/concertados-webapp/target/test-reports

問題

Draftのフィールドは、値としてname渡すと null として設定されます''

私は何が欠けていますか?. 前もって感謝します。

SIMPLE TEST も失敗

def "test blank constraints"() {
          when: 'the name and subjects are blank'
          def d = new Draft(name: '', subject:'')

          then: 'the validation should fail with blank errors'
          !d.validate()
          'blank' == d.errors["name"]
          'blank' == d.errors["subject"]
   }

これはエラーです:

| Running 1 spock test... 1 of 1
--Output from test blank constraints--
| Error --Output from test blank constraints--
| Failure:  test blank constraints(com.softamo.concertados.DraftSpec)
|  Condition not satisfied:

'blank' == d.errors["name"]
        |  | |     |
        |  | |     nullable
        |  | org.codehaus.groovy.grails.plugins.testing.GrailsMockErrors: 3 errors
4

2 に答える 2

7

Time_yatesは問題を指摘しました:

http://grails.org/doc/latest/ref/Constraints/nullable.html

フォームの送信による Web リクエストには、値のない入力フィールドに対して、null ではなく空白の文字列が含まれます。null 許容ではないプロパティに一括プロパティ バインディングを行う場合は、この点に注意してください。デフォルトの動作では、データ バインダーが空白文字列を null に変換するため、空白文字列は nullable: false に対して検証されません。これには、空の文字列と空白の文字列が含まれます。空白文字列は、trim() メソッドが空の文字列を返すような任意の文字列です。空の文字列から null への変換をオフにするには、Config.groovy で grails.databinding.convertEmptyStringsToNull プロパティを false に設定します。データ バインディングの詳細については、データ バインディングのセクションを参照してください。

于 2013-11-08T09:14:52.123 に答える
0

Grails 2.3.9 の場合、このテストでは、上記の構成設定 (then ステートメントで確認) を使用している場合でも、空白の制約に関する問題が強調表示されます。

問題を追跡できませんでした。BlankConstraint は null プロパティをチェックせず、空白と null 許容の制約は両方とも拒否可能であるため、1 つが失敗すると、他のすべてが無視されます。

テスト中のクラス:

package test

class TestVetoableConstraints {
    String nullableAndBlank
    String nullableAndNotBlank
    String notNullableAndBlank
    String notNullableAndNotBlank

    static constraints = {
    nullableAndBlank(nullable:true, blank:true)
    nullableAndNotBlank(nullable:true, blank:false)
    notNullableAndBlank(nullable:false, blank:true)
    notNullableAndNotBlank(nullable:false, blank:false)
    }
}

テスト:

package test

import grails.test.mixin.TestFor
import spock.lang.Specification
import grails.util.Holders

@TestFor(TestVetoableConstraints)
class TestVetoableConstraintsSpec extends Specification {
    def config = Holders.config

    void "test nullable and blank constraints" (error, field, val) {
        when: 
            mockForConstraintsTests(TestVetoableConstraints)
            def obj = new TestVetoableConstraints("$field": val)

        then: 
// These are set to ensure that an empty string isn't trimmed and converted to null
            false == config.grails.databinding.convertEmptyStringsToNull
            false == config.grails.databinding.trimStrings
            validateConstraints(obj, field, error)

        where:
            error                  | field                      | val
            'valid'                | 'nullableAndBlank'         | null
            'valid'                | 'nullableAndBlank'         | ''
            'valid'                | 'nullableAndBlank'         | 'Good String'
            'valid'                | 'nullableAndNotBlank'      | null
// The next test should return blank, but actually fails on "assert obj.errors[field]" which is null
            'blank'                | 'nullableAndNotBlank'      | ''
            'valid'                | 'nullableAndNotBlank'      | 'Good String'
            'nullable'             | 'notNullableAndBlank'      | null
// The next test should be valid, but actually fails on "assert !obj.errors[field]" which returns 'nullable'
            'valid'                | 'notNullableAndBlank'      | ''
            'valid'                | 'notNullableAndBlank'      | 'Good String'
            'nullable'             | 'notNullableAndNotBlank'   | null
// The next test should return blank, but actually fails on "assert error == obj.errors[field]" because it returns 'nullable'
            'blank'                | 'notNullableAndNotBlank'   | ''
            'valid'                | 'notNullableAndNotBlank'   | 'Good String'
    }

    private void validateConstraints(obj, field, error) {
       def validated = obj.validate()
       if (error && error != 'valid') {
           assert !validated
           assert obj.errors[field]
           assert error == obj.errors[field]
       } else {
           assert !obj.errors[field]
       }
   }
}
于 2014-06-12T15:26:00.857 に答える