在 REST-assured 中使用 groovy 闭包对 JSON 进行嵌套迭代
Nested iteration over JSON using groovy closure in REST-assured
我的 REST 端点有以下 JSON 响应:
{
"response": {
"status": 200,
"startRow": 0,
"endRow": 1,
"totalRows": 1,
"next": "",
"data": {
"id": "workflow-1",
"name": "SampleWorkflow",
"tasks": [
{
"id": "task-0",
"name": "AWX",
"triggered_by": ["task-5"]
},
{
"id": "task-1",
"name": "BrainStorming",
"triggered_by": ["task-2", "task-5"]
},
{
"id": "task-2",
"name": "OnHold",
"triggered_by": ["task-0", "task-4", "task-7", "task-8", "task9"]
},
{
"id": "task-3",
"name": "InvestigateSuggestions",
"triggered_by": ["task-6"]
},
{
"id": "task-4",
"name": "Mistral",
"triggered_by": ["task-3"]
},
{
"id": "task-5",
"name": "Ansible",
"triggered_by": ["task-3"]
},
{
"id": "task-6",
"name": "Integration",
"triggered_by": []
},
{
"id": "task-7",
"name": "Tower",
"triggered_by": ["task-5"]
},
{
"id": "task-8",
"name": "Camunda",
"triggered_by": ["task-3"]
},
{
"id": "task-9",
"name": "HungOnMistral",
"triggered_by": ["task-0", "task-7"]
},
{
"id": "task-10",
"name": "MistralIsChosen",
"triggered_by": ["task-1"]
}
]
}
}
}
我正在使用带 groovy gpath 表达式的 rest-assured 进行提取,如下所示:
given()
.when()
.get("http://localhost:8080/workflow-1")
.then()
.extract()
.path("response.data.tasks.findAll{ it.triggered_by.contains('task-3') }.name")
正确地给了我 [Mistral, Ansible, Camunda]
我想要实现的是找到由 InvestigateSuggestions
任务触发的任务名称。但是我不确定我必须传递给 contains()
的 taskId 是 task-3
;我只知道它的名字,即 InvestigateSuggestions
。所以我尝试这样做:
given()
.when()
.get("http://localhost:8080/workflow-1")
.then()
.extract()
.path("response.data.tasks.findAll{
it.triggered_by.contains(response.data.tasks.find{
it.name.equals('InvestigateSuggestions')}.id) }.name")
不起作用并抱怨参数 "response" 已被使用但未定义。
如何从 findAll 闭包内部迭代外部集合以找到正确的 id
传递给 contains()
??
我不确定这是否符合习惯,但一种方法是先找到 id
,然后代入另一个查询:
@Test
void testCase1() {
def json = given()
.when()
.get("http://localhost:5151/egg_minimal/stacko.json")
// e.g. id = 'task-3' for name 'InvestigateSuggestions'
def id = json
.then()
.extract()
.path("response.data.tasks.find { it.name == 'InvestigateSuggestions' }.id")
// e.g. tasks have name 'task-3'
def tasks = json
.then()
.extract()
.path("response.data.tasks.findAll{ it.triggered_by.contains('${id}') }.name")
assertEquals(['Mistral', 'Ansible', 'Camunda'], tasks)
}
你可以利用一个肮脏的秘密,restAssuredJsonRootObject
。这是未记录的(并且可能会发生变化,尽管据我所知,在 REST Assured 的 7 年以上生命周期中它从未发生过变化)。
这将允许你写:
given()
.when()
.get("http://localhost:8080/workflow-1")
.then()
.extract()
.path("response.data.tasks.findAll{
it.triggered_by.contains(restAssuredJsonRootObject.response.data.tasks.find{
it.name.equals('InvestigateSuggestions')}.id) }.name")
如果你不想使用这个 "hack" 那么你需要做一些类似于 Michael Easter proposed in his .
的事情
当谈到基于响应主体生成匹配器时,情况就更好了。请参阅文档 here.
我的 REST 端点有以下 JSON 响应:
{
"response": {
"status": 200,
"startRow": 0,
"endRow": 1,
"totalRows": 1,
"next": "",
"data": {
"id": "workflow-1",
"name": "SampleWorkflow",
"tasks": [
{
"id": "task-0",
"name": "AWX",
"triggered_by": ["task-5"]
},
{
"id": "task-1",
"name": "BrainStorming",
"triggered_by": ["task-2", "task-5"]
},
{
"id": "task-2",
"name": "OnHold",
"triggered_by": ["task-0", "task-4", "task-7", "task-8", "task9"]
},
{
"id": "task-3",
"name": "InvestigateSuggestions",
"triggered_by": ["task-6"]
},
{
"id": "task-4",
"name": "Mistral",
"triggered_by": ["task-3"]
},
{
"id": "task-5",
"name": "Ansible",
"triggered_by": ["task-3"]
},
{
"id": "task-6",
"name": "Integration",
"triggered_by": []
},
{
"id": "task-7",
"name": "Tower",
"triggered_by": ["task-5"]
},
{
"id": "task-8",
"name": "Camunda",
"triggered_by": ["task-3"]
},
{
"id": "task-9",
"name": "HungOnMistral",
"triggered_by": ["task-0", "task-7"]
},
{
"id": "task-10",
"name": "MistralIsChosen",
"triggered_by": ["task-1"]
}
]
}
}
}
我正在使用带 groovy gpath 表达式的 rest-assured 进行提取,如下所示:
given()
.when()
.get("http://localhost:8080/workflow-1")
.then()
.extract()
.path("response.data.tasks.findAll{ it.triggered_by.contains('task-3') }.name")
正确地给了我 [Mistral, Ansible, Camunda]
我想要实现的是找到由 InvestigateSuggestions
任务触发的任务名称。但是我不确定我必须传递给 contains()
的 taskId 是 task-3
;我只知道它的名字,即 InvestigateSuggestions
。所以我尝试这样做:
given()
.when()
.get("http://localhost:8080/workflow-1")
.then()
.extract()
.path("response.data.tasks.findAll{
it.triggered_by.contains(response.data.tasks.find{
it.name.equals('InvestigateSuggestions')}.id) }.name")
不起作用并抱怨参数 "response" 已被使用但未定义。
如何从 findAll 闭包内部迭代外部集合以找到正确的 id
传递给 contains()
??
我不确定这是否符合习惯,但一种方法是先找到 id
,然后代入另一个查询:
@Test
void testCase1() {
def json = given()
.when()
.get("http://localhost:5151/egg_minimal/stacko.json")
// e.g. id = 'task-3' for name 'InvestigateSuggestions'
def id = json
.then()
.extract()
.path("response.data.tasks.find { it.name == 'InvestigateSuggestions' }.id")
// e.g. tasks have name 'task-3'
def tasks = json
.then()
.extract()
.path("response.data.tasks.findAll{ it.triggered_by.contains('${id}') }.name")
assertEquals(['Mistral', 'Ansible', 'Camunda'], tasks)
}
你可以利用一个肮脏的秘密,restAssuredJsonRootObject
。这是未记录的(并且可能会发生变化,尽管据我所知,在 REST Assured 的 7 年以上生命周期中它从未发生过变化)。
这将允许你写:
given()
.when()
.get("http://localhost:8080/workflow-1")
.then()
.extract()
.path("response.data.tasks.findAll{
it.triggered_by.contains(restAssuredJsonRootObject.response.data.tasks.find{
it.name.equals('InvestigateSuggestions')}.id) }.name")
如果你不想使用这个 "hack" 那么你需要做一些类似于 Michael Easter proposed in his
当谈到基于响应主体生成匹配器时,情况就更好了。请参阅文档 here.