Issue
Today I need to create an integration test for public API consumer and check if the records which I found matches the query param.
For example, I am sending a GET request like
localhost:8080/nutritionix/productDetails?query=grilled
and I want to find out each product which contains "grilled" or "Grilled" or the same phrase in other forms, e.g: "GRillEd" phrase in food_name field.
Example response from public API:
[
{
"food_name": "chicken grilled",
"serving_qty": 1,
"serving_unit": "piece",
"photo": {
"thumb": "https://d2xdmhkmkbyw75.cloudfront.net/1714_thumb.jpg"
}
},
{
"food_name": "grilled chicken thigh",
"serving_qty": 1,
"serving_unit": "thigh with skin",
"photo": {
"thumb": "https://d2xdmhkmkbyw75.cloudfront.net/8724_thumb.jpg"
}
},
{
"food_name": "grilled chicken wrap",
"serving_qty": 1,
"serving_unit": "wrap",
"photo": {
"thumb": "https://d2xdmhkmkbyw75.cloudfront.net/2562_thumb.jpg"
}
},
{
"food_name": "grilled cheese",
"serving_qty": 1,
"serving_unit": "sandwich",
"photo": {
"thumb": "https://d2xdmhkmkbyw75.cloudfront.net/1763_thumb.jpg"
}
},
{
"food_name": "Grilled Tilapia, Signature Grilled",
"serving_qty": 1,
"serving_unit": "fillet",
"brand_name": "Gorton's",
"nix_brand_id": "51db37b2176fe9790a8985bc",
"photo": {
"thumb": "https://d1r9wva3zcpswd.cloudfront.net/55178d395108f25f51667c2d.jpeg"
}
},
{
"food_name": "Grilled Gourmet Soft Taco, Grilled Chicken",
"serving_qty": 189,
"serving_unit": "g",
"brand_name": "Amigos Kings Classic",
"nix_brand_id": "521b95434a56d006cae297dc",
"photo": {
"thumb": "https://d2eawub7utcl6.cloudfront.net/images/nix-apple-grey.png"
}
}
]
Test class below:
@ExtendWith(SpringExtension.class)
@AutoConfigureMockMvc
@SpringBootTest
class NutritionixApiControllerTest {
@Autowired
private MockMvc mockMvc;
@Test
void nutritionixSearchInstantTest() throws Exception {
ResultActions resultActions = mockMvc
.perform(MockMvcRequestBuilders.get("/nutritionix/productDetails?query=grilled")
.contentType(MediaType.APPLICATION_JSON)).andDo(print())
.andExpect(MockMvcResultMatchers.status().isOk())
.andExpect(MockMvcResultMatchers.jsonPath("$", hasSize(40)))
.andExpect(MockMvcResultMatchers.jsonPath("$[*].food_name", hasItems("grilled")))
.andExpect(MockMvcResultMatchers.jsonPath("$[0].food_name", containsString("grilled")));
}
Unfortunately, the line:
.andExpect(MockMvcResultMatchers.jsonPath("$[*].food_name", hasItems("grilled")))
leading to the assertion error like:
java.lang.AssertionError: JSON path "$[*].food_name"
Expected: (a collection containing "grilled")
but: a collection containing "grilled" was "grilled chicken thigh", was "Fiesta Grilled Chicken", was "grilled zucchini", was "grilled octopus", was "grilled veggies", was "Grilled Chicken Pesto with Vegetables", was "Grilled Chicken Salad", was "grilled cheese", was "Grilled Chicken Strips", was "Grilled Chicken for Grilled Chicken Salad", was "grilled chicken", was "chicken grilled", was "Grilled Chicken Marinara, with Parmesan", was "Greek Dressing for Grilled Topped Salads", was "chilis grilled chicken salad", was "Caesar Dressing for Grilled Topped Salads", was "grilled onions", was "Grilled & Ready Grilled Chicken Breast Chunks", was "Grilled Cali Bowl, Grilled", was "Mesquite Grilled Chicken Fillets", was "grilled chicken salad", was "Grilled Chicken Marsala", was "Grilled Gourmet Soft Taco, Grilled Chicken", was "Grilled Chicken & Broccoli Alfredo", was "grilled salmon", was "Fire-Grilled Grilled Steak Salad", was "Grilled Tilapia, Signature Grilled", was "Grilled Salmon, Classic Grilled", was "Grilled Basil Chicken", was "grilled steak", was "grilled chicken wrap", was "grilled chicken sandwich", was "Big Sky Grilled Salad (grilled chicken)", was "grilled fish", was "Grilled Roll-Up, Grilled Chicken", was "grilled shrimp", was "grilled hamburger", was "grilled chicken breast", was "grilled vegetables", was "grilled asparagus"
All I want to achieve is to check if all the objects that I received in JSON response contain a phrase in the food_name field, which we passed as query params during the query, including lowercase and uppercase letters and funny text cases.
I suppose the problem arose because of the lack of standardization of the returned records schema, for example: sometimes we get objects with food_name field, which are upper case and sometimes lower case.
Thanks for any help on how to improve my JSONPath syntax.
Solution
The problem is that you are checking if any element of the result is equal to grilled
. What I think you need to check is if every element of the result contains grilled ignoring case.
Using the library Hamcrest (I think you are already using it) you can do it in the following way:
@Test
public void everyContainsStringIgnoringCase() {
List<String> foodNames = JsonPath.read(RESPONSE, "$[*].food_name");
assertThat(foodNames, Every.everyItem(containsStringIgnoringCase("grilled")));
}
where RESPONSE is you json.
Answered By - Ezequiel