当我希望在许多类似的字段上执行相同的测试时,如何在Grails Spock测试中迭代测试?

时间:2015-07-02 11:45:34

标签: grails integration-testing spock

我有一个包含属性对的域类:

Boolean statement1
Boolean statement1Missing

这些对最多可达九个。

以下约束适用于每个配对:

    statement1                  nullable: true
    statement1Missing           validator: {val, obj ->
                                    if ( val == true &&
                                        (obj.statement1 == true || obj.statement1 == false)) {
                                        return ['statement.not.missing', 1] 
                                    }
                                    if (obj.statement1 == null && val == false) {
                                        return ['statement.is.missing', 1]
                                    }
                                }

我设计了一个可以容纳一对语句的集成测试:

@Unroll
def "Validation of custom validation for statement1"() {

    given: "New data"
    def participant = new Data(studyId:     "M00001",
                                            formVersion:    Version.get(7)                          
                                           )

    and: "an initial set of test values"
    participant.statement1 = statement1
    participant.statement1Missing = statement1Missing

    when: "the validator is invoked"
    def isValidConsentData = participant.validate()

    then: "the appropriate fields are flagged as errors"
    isValidConsentData == anticipatedValid
    participant.errors.getFieldError(fieldInError)?.code == errorCode

    where:

    statement1  | statement1Missing | anticipatedValid  | fieldInError          | errorCode
    true        | false             | true              | null                  | null
    false       | false             | true              | null                  | null
    null        | true              | true              | null                  | null
    null        | false             | false             | "statement1Missing"   | "statement.is.missing"
    true        | true              | false             | "statement1Missing"   | "statement.not.missing"
    false       | true              | false             | "statement1Missing"   | "statement.not.missing"
}

它处理我想测试的statement1的所有组合。

我一直试图弄清楚如何为所有九个语句对重复这个测试。我试过这样的循环:

    (1..9).each { statementNo
        ...
        and ...
        participant.("statement" + statementNo) = ("statement" + statementNo)
        ...
        where:
        ("statement" + StatementNo) | ("statement" + StatementNo + Missing) | ...
    }

我之前想要迭代属性时使用过这种类型的迭代,但它在Spock中不起作用。测试完全被忽略了。我真的不想为每个语句对重复这段代码。

我已经研究过使用这种类型的结构http://www.christianoestreich.com/2012/11/domain-constraints-grails-spock-updated/,但这只允许你一次测试一个属性值,而我想多次测试一个属性值。

另一种选择是明确地在'其中'中包含每个属性对。阻止和每一个可能的结果,但这将非常麻烦。

请提供一些关于如何使用迭代结构来执行这些测试的建议。

1 个答案:

答案 0 :(得分:1)

如下:

...    

and: "an initial set of test values"
(1..9).each { statementNo ->
    participant."statement$statementNo" = statement
    participant."statement${statementNo}Missing" = statementMissing
}

when: "the validator is invoked"
def isValidConsentData = participant.validate()

then: "the appropriate fields are flagged as errors"
(1..9).each { statementNo ->
    def fieldInError
    if (anticipatedValid) {
        fieldInError = null
    } else {
        fieldInError = "statement${statementNo}Missing"
    }
    assert isValidConsentData == anticipatedValid
    assert participant.errors.getFieldError(fieldInError)?.code == errorCode
}

where:
statement  | statementMissing | anticipatedValid | errorCode
true       | false            | true             | null
false      | false            | true             | null
null       | true             | true             | null
null       | false            | false            | "statement.is.missing"
true       | true             | false            | "statement.not.missing"
false      | true             | false            | "statement.not.missing"

当给定字段没有错误时,不确定它对getFieldError(fieldName)的行为如何,因此如果抛出异常,您可能需要使用!anticipatedValid为第二个断言添加一些条件。

重要的是隐式assert是必要的,因为each是无效的,因此测试根本不会检查任何内容。