在使用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
应该为空(“预期为空的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()
}
能做到吗?
答案 0 :(得分:1)
为此,我将创建两个独立的测试,一个针对每个不同响应形状的测试,并为每个响应形状提供一个提供者状态,例如given there are type b answers
。
这样,当您在提供方进行验证时,它只会发送这两种字段类型。
两个示例的并集给出了允许两者的契约。
答案 1 :(得分: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