0

我需要帮助来使用 pact-jvm ( https://github.com/DiUS/pact-jvm ) 编写我的消费者契约。

我的问题是我有一个字段是地图列表(数组)。每个地图可以有不同类型的元素(字符串或子地图),例如。

"validatedAnswers": [
    {
      "type": "typeA",
      "answers": {
        "favourite_colour": "Blue",
        "correspondence_address": {
            "line_1": "Main St",
            "postcode": "1A 2BC",
            "town": "London"
        }
      }
    },
    {
      "type": "typeB",
      "answers": {
        "first_name": "Firstname",
        "last_name": "Lastname",
      }
    }
  ]

但我们只对其中一些答案感兴趣。

注意:以上只是显示validatedAnswers. 每张answers地图都有几十个元素。

我们真正需要的是:https ://github.com/pact-foundation/pact-specification/issues/38 ,但它计划用于 v.4。与此同时,我们正在尝试不同的方法。我现在尝试做的是指定列表的每个元素都是非空映射。另一种方法是指定列表的每个元素都不为空。这些都可以使用 Groovy DSL 完成吗?

这个:

new PactBuilder().serviceConsumer('A').hasPactWith('B')
.port(findAvailablePort()).uponReceiving(...)
.willRespondWith(status: 200, headers: ['Content-Type': 'application/json'])
.withBody {
  validatedAnswers minLike(1) {
     type string()
     answers {
     }
  }
}

不起作用,因为它意味着answers预期为空(“预期为空地图但收到地图([...])”,另请参见https://github.com/DiUS/pact-jvm/issues/298) .

所以我想做的是这样的:

.withBody {
    validatedAnswers minLike(1) {
         type string()
         answers Matchers.map()
    }
}

或者:

validatedAnswers minLike(1) {
     type string()
     answers {
             keyLike 'title', notNull()
     }
}

或者:

validatedAnswers minLike(1) {
     type string()
     answers notNull()
}

可以做到吗?

4

2 回答 2

1

我会为此创建两个单独的测试,一个针对每个不同响应形状的测试,并为每个例如提供一个提供者状态given there are type b answers

这样,当您在提供者端进行验证时,它只会发送这两种字段类型。

这两个例子的联合给出了一个允许两者的合同。

于 2018-07-28T00:12:32.530 回答
0

你可以在没有 DSL 的情况下做到这一点,示例 Groovy 脚本:

class ValidateAnswers {
    static main(args) {
        /* Array with some samples */
        List<Map> answersList = [
            [
                type: 'typeA',
                answers: [
                    favourite_colour: 'Blue',
                    correspondence_address: [
                        line_1: 'Main St',
                        postcode: '1A 2BC',
                        town: 'London'
                    ]
                ]
            ],
            [
                type: 'typeB',
                answers: [
                    first_name: 'Firstname',
                    last_name: "Lastname"
                ]
            ],
            [
                type: 'typeC',
                answers: null
            ],
            [
                type: 'typeD'
            ],
            [
                type: 'typeE',
                answers: [:]
            ]
        ]

        /* Iterating through all elements in list above */
        for (answer in answersList) {
            /* Print result of checking */
            println "$answer.type is ${validAnswer(answer) ? 'valid' : 'not valid'}"
        }
    }

    /**
    * Method to recursive iterate through Map's.
    * return true only if value is not an empty Map and it key is 'answer'.
    */
    static Boolean validAnswer(Map map, Boolean result = false) {
        map.each { key, value ->
            if (key == 'answers') {
                result = value instanceof Map && value.size() > 0
            } else if (value instanceof Map) {
                validAnswer(value as Map, false)
            }
        }

        return result
    }
}

输出是:

typeA is valid
typeB is valid
typeC is not valid
typeD is not valid
typeE is not valid
于 2018-07-25T23:43:38.120 回答