我需要帮助使用pact-jvm编写我的消费者pact(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,但计划在第4版。与此同时,我们正在尝试一种不同的方法。我现在要做的是指定列表中的每个元素都是非空映射。另一种方法是指定列表中的每个元素都不为null。这些都可以使用GroovySSL完成吗?
此:
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
应为空("应为空Map,但收到Map([…](",另请参阅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()
}
能做到吗?
我会为此创建两个单独的测试,每个不同的响应形状都有一个测试,每个测试都有一种提供者状态,例如given there are type b answers
。
这样,当您在提供者端验证时,它将只发送这两种字段类型。
这两个例子的结合给出了一个允许两者结合的合同。
您可以在没有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