使用REST保证的groovy闭包对JSON进行嵌套迭代

问题描述 投票:1回答:2

我的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表达式进行提取,如下所示:

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()的任务是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")

这不起作用,并抱怨使用参数“响应”但未定义。

如何从findAll闭包内迭代外部集合以找到正确的id传递到contains()

groovy rest-assured rest-assured-jsonpath
2个回答
3
投票

你可以利用一个肮脏的秘密,restAssuredJsonRootObject。这是没有记录的(并且可以改变,尽管在7年+ REST保证的生命周期中它永远不会改变)。

这将允许你写:

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")

如果你不想使用这个“黑客”,那么你需要做一些类似于Michael Easter在他的answer中提出的建议。

当基于响应主体生成匹配器时,故事更好。请参阅docs here


1
投票

我不确定这是否是惯用的,但一种方法是首先找到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)
}
© www.soinside.com 2019 - 2024. All rights reserved.