REST Assured:如何使用JSON中的嵌套属性查找元素并验证其他属性

Cla*_*key 2 java hamcrest rest-assured spring-boot mockmvc

我保证经验有限.我们有很多测试,我通常可以在google中找到示例,或者google失败,但是当我尝试在匿名数组中的元素的嵌套属性上匹配时,我被困住了,并且向上和向下验证属性(cousins?) .

示例JSON:

[  
   {  
      "id":1,
      "type":{  
         "typeId":3,
         "name":"LPM"
      },
      "status":{  
         "id":1,
         "price":1.20,
         "source":172,
         "valid":0
      }
   },
   {  
      "id":2,
      "type":{  
         "typeId":2,
         "name":"ST"
      },
      "status":{  
         "id":10,
         "price":1.20,
         "source":172,
         "valid":0
      }
   }
]
Run Code Online (Sandbox Code Playgroud)

我使用的是放心了,我想找到有列表中的元素type.name等于LPM,然后再验证status.price,status.source以及status.id只有元素.

当我最初开始验证响应时,只有一个项目可以在数组中,所以我使用:

response.then()
        .assertThat()
        .body("size", greaterThan(0))
        .body("[0].type.name", equalToIgnoringCase("LPM"))
        .body("[0].status.id", equalTo(statusId))
        .body("[0].status.source", equalTo(sourceId))
        .body("[0].status.price", equalTo(price));
Run Code Online (Sandbox Code Playgroud)

但是,这不再有效,因为数组中可能有多个元素,并且无法保证顺序.

我修改了我的身体检查:

response.then()
        .assertThat()
        .body("size", greaterThan(0))
        .body("type.name", hasItem("LPM"))
        .body("status.id", hasItem(statusId))
        .body("status.source", hasItem(sourceId))
        .body("status.price", hasItem(price));
Run Code Online (Sandbox Code Playgroud)

这是足以让测试通过,但这种引入的风险status.id,status.source以及status.price与元素type.nameLPM可能是不正确的,但因为他们对与元素相匹配,这将不会被检测到type.nameST.

所以,我希望能够找到具有LPM,因为它的元素type.name,其中我可以保证那里只有一个,然后status.id,status.sourcestatus.price,只检查元素,即将ST元素.

我试图修改我的身体匹配器以找到type.name我需要的元素,但是我不能让它工作,因为我无法弄清楚如何在树上,向上和向下,以检查其他属性在同一元素中:

response.then()
        .assertThat()
        .body("size", greaterThan(0))
        .body("$.findAll (it.type.name = LPM}.status.id ", hasItem(statusId))
        .body("$.findAll (it.type.name = LPM}.status.source", hasItem(sourceId))
        .body("$.findAll (it.type.name = LPM}.status.price", hasItem(price));
Run Code Online (Sandbox Code Playgroud)

即使这有效,它也会在真正曾经做过的时候搜索树3次.

我的中间比赛现在已经过了这个测试,但我想要做到这一点.我知道我可以把元素放到一个List并从那里开始工作,但为了与我们的其他例子保持一致,我宁愿不这样做,尽管我目前看不到另一种选择.

我试图找到我在文档,多个放心的教程和示例中尝试做的示例,但我没有,所以总有可能实际上不可能.如果不是,我很乐意教育背后的理论.

任何帮助赞赏.

Joh*_*han 8

这是一种方法:

...
then().
        root("find {it.type.name == '%s'}.status").
        body("id", withArgs("LPM"), is(1)).
        body("price", withArgs("LPM"), is(1.20f)).
        body("source", withArgs("LPM"), is(172)).
        body("id", withArgs("ST"), is(10));
Run Code Online (Sandbox Code Playgroud)

(你显然可以提取withArgs变量以避免重复).

find是Groovy找到匹配谓词({it.type.name == '%s'})的第一个元素的方法,findAll将始终返回一个列表.

root指示REST Assured使用后续期望中使用的"根路径"(请参阅文档).