在REST保证的情况下使用groovy闭包在JSON上嵌套嵌套迭代

时间:2018-08-31 20:54:18

标签: groovy rest-assured rest-assured-jsonpath

我的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()的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()

2 个答案:

答案 0 :(得分:3)

您可以利用肮脏的秘密restAssuredJsonRootObject。这是没有记录的(尽管据我所记得的REST保证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")

如果您不想使用此“骇客”,则需要执行类似于Michael Easter在其answer中提出的建议。

在根据响应主体生成匹配器时,故事会更好。参见文档here

答案 1 :(得分: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)
}