WebTestClient check jsonPath against another jsonPath - java

I have this "content" response from which I need to assert some values.
WebTestClient.BodyContentSpec content = response.expectStatus().isOk()
.expectBody()
.jsonPath("$.path1").isEqualTo(value1);
If I want to assert some JSON paths with predefined values all is good.
But the tricky part comes when I wanna check if a JSON path is equal to another JSON path.
JsonPathAssertions jsonPath2 = bodyContentSpec.jsonPath("$.path2");
JsonPathAssertions jsonPath3 = bodyContentSpec.jsonPath("$.path3");
So my question is how can I assert the content of jsonPath2 against jsonPath3 using org.hamcrest.Matchers.greaterThanOrEqualTo?

I think you could use the value(Consumer) method:
for simple operations:
jsonPath2.value(v->jsonPath3.isEqualTo(v));
for using special Matchers:
jsonPath2.value(v->jsonPath3.value(Matchers.greaterThanOrEqualTo(v)));

Related

Convert XML to and from Java

I am trying to get the XML response from the rest API. And I am getting JSON response for all customers and XML for single customer from API. PFB the screen print for the case for both cases:
Case 1: When URL= http://localhost:8080/spring-crm-rest/api/customers/ then I am getting JSON response
JSON Response
Case 2: When URL = http://localhost:8080/spring-crm-rest/api/customers/1 then I am getting XML response
XML Response
Please find below the URL for the complete code to replicate the same at your end.
Link for the code: https://drive.google.com/file/d/1fd7DyUsfOvY4fX0nm6j4fzrwxHyg9ZGz/view?usp=sharing
Ok I think the reason why that happens is the following:
the path /spring-crm-rest/api/customers/ has return type List<Customer> -> default java List as top level -> json result
while /spring-crm-rest/api/customers/1 has return type Customer as top level which has the javax.xml.bind annotations -> xml result
Changing this may be a bit tricky but these are some possible things you can try:
specifically set the content type of the endpoint like this: #GetMapping(produces = {"application/json"})
removing the #Xml.* annotations -> spring will can serialize the class without any annotations but without them you have less of a control over the resulting json (e.g. renaming fields, etc). Depending on your usecase it might not be needed though

Using JsonPath to parse JSON String recursively

I'm trying to parse a given JSON in String format, for example:
{
"id": "indeed",
"interaction_data":
"{\"data\":\"{\\\"something\\\":\\\"blabla\\\"}\",\"somethingElseNotNested\":\"Indeed\"}"
}
I'm working with Kotlin, and I called JsonPath.parse on the value above, the problem is, interaction_data is parsed as a String, instead of it being treated as a JSON as well.
So when I call read("$.interaction_data.data.something") it gives me an error, since interaction_data is treated as a String, instead of an object.
Any way around this? (other than parsing this part separately, I need to handle this generically).
Thanks!
Json interaction_data property is triple stringifyied. Why you don't try this
var jsonObject=..your json;
var jsonParsed=JSON.parse(jsonObject.interaction_data);
jsonParsed.data=JSON.parse(jsonParsed.data);
JsonObject.interaction_data=jsonParsed;
result
{
"id":"indeed",
"interaction_data":{"data"{"something":"blabla"},"somethingElseNotNested":"Indeed"}
}

mockMvc assert that content is null (content is not json)

I want to assert that the returned content (model and view) are both null on certain conditions but I can't find the right Matcher. Could someone please show me how this should be done? If this problem was solved in another thread I apologize I could not find it.
mockMvc.perform(get("/test")
.headers(assembleBasicAuthHeader("idontexist", "gibberish")))
.andExpect(status().isForbidden())
.andExpect(content().isNull()) //this obviously doesnt work
.andExpect(model().isNull()) //this obviously doesnt work
.andExpect(status().reason(containsString("Forbidden")));
Assuming your API supports JSON (it's not clear from your question), one way would be to assert the response body using JSON path expressions:
mockMvc.perform(get(..)
.headers(..)
.accept(MediaType.APPLICATION_JSON))
.andExpect(status().isForbidden())
.andExpect(status().reason(..))
.andExpect(jsonPath("$").doesNotExist());

Why my list is empty when I am parsing correct json response?

I am trying to print the ids from a JSON response. But I am not able to understand why I am getting a blank list. I have verified the JSONpath (SECTIONS_IDS_JSONPATH) from the online website and it is giving me correct results.
public static void main(String[] args) {
String SECTIONS_IDS_JSONPATH = "$.[*].instructionEvents[*].sectionId";
String sectionsData = "{\"sections\":[{\"id\":\"8da1cf5d-3150-4e11-b2af-338d1df20475\",\"courseId\":\"e8a65581-ed1c-43f0-90a7-7b9d51b35062\",\"courseCredits\":[{\"minimum\":4,\"maximum\":null,\"measure\":\"hour\",\"increment\":null}],\"academicPeriodId\":\"8b7a8e9e-5417-42a3-9c90-8d47226b5987\",\"reservedSeatsMaximum\":0,\"maxEnrollment\":0,\"hours\":[],\"sites\":[\"All Campuses\"],\"instructors\":[],\"instructionEvents\":[{\"id\":\"9d0c49e2-1579-43c3-b25a-2f85f551e62d\",\"sectionId\":\"8da1cf5d-3150-4e11-b2af-338d1df20475\",\"courseId\":\"e8a65581-ed1c-43f0-90a7-7b9d51b35062\",\"days\":[\"monday\",\"wednesday\",\"friday\"],\"startTm\":\"2019-01-01T09:45:00-05:00\",\"endTm\":\"2024-12-01T10:45:00-05:00\",\"localizations\":[],\"instructionalMethod\":\"Lecture\"}]},{\"id\":\"ad3f63ad-e642-4938-a9fd-318afd2d1ad0\",\"courseId\":\"e8a65581-ed1c-43f0-90a7-7b9d51b35062\",\"courseCredits\":[{\"minimum\":4,\"maximum\":null,\"measure\":\"hour\",\"increment\":null}],\"academicPeriodId\":\"8b7a8e9e-5417-42a3-9c90-8d47226b5987\",\"reservedSeatsMaximum\":0,\"maxEnrollment\":20,\"hours\":[],\"sites\":[\"All Campuses\"],\"instructors\":[{\"id\":\"c26572de-f9c8-4623-ba6a-79997b33f1c6\",\"sectionId\":\"ad3f63ad-e642-4938-a9fd-318afd2d1ad0\",\"role\":\"primary\",\"persons\":[{\"id\":\"c1b50d79-5505-4a33-9316-b4b1f52c0ca3\",\"names\":[{\"firstName\":\"BanColoFac-1\",\"lastName\":\"CTester\",\"preferred\":true}]}]}],\"instructionEvents\":[{\"id\":\"af8fb500-29f5-4451-95d5-a11215298cd4\",\"sectionId\":\"ad3f63ad-e642-4938-a9fd-318afd2d1ad0\",\"courseId\":\"e8a65581-ed1c-43f0-90a7-7b9d51b35062\",\"days\":[\"tuesday\",\"thursday\"],\"startTm\":\"2019-01-01T10:00:00-05:00\",\"endTm\":\"2024-12-01T10:50:00-05:00\",\"localizations\":[],\"instructionalMethod\":\"Lecture\"}]},{\"id\":\"a1422391-e2b9-4bc4-907b-371fcea01d70\",\"courseId\":\"e8a65581-ed1c-43f0-90a7-7b9d51b35062\",\"courseCredits\":[{\"minimum\":4,\"maximum\":null,\"measure\":\"hour\",\"increment\":null}],\"academicPeriodId\":\"8b7a8e9e-5417-42a3-9c90-8d47226b5987\",\"reservedSeatsMaximum\":0,\"maxEnrollment\":20,\"hours\":[],\"sites\":[\"All Campuses\"],\"instructors\":[{\"id\":\"808daae1-3ec6-47ec-9af0-5392199bdf78\",\"sectionId\":\"a1422391-e2b9-4bc4-907b-371fcea01d70\",\"role\":\"primary\",\"persons\":[{\"id\":\"793cc9b3-57c7-4a2d-8984-07a1fb6834a9\",\"names\":[{\"firstName\":\"Andrew\",\"lastName\":\"Adams\",\"preferred\":true}]}]}],\"instructionEvents\":[{\"id\":\"730b4206-684d-4413-bf20-9bec5c1dc900\",\"sectionId\":\"a1422391-e2b9-4bc4-907b-371fcea01d70\",\"courseId\":\"e8a65581-ed1c-43f0-90a7-7b9d51b35062\",\"days\":[\"tuesday\",\"thursday\"],\"startTm\":\"2019-01-01T10:00:00-05:00\",\"endTm\":\"2024-12-01T10:50:00-05:00\",\"localizations\":[],\"instructionalMethod\":\"Lecture\"},{\"id\":\"8bc059ab-a8f8-4469-8e79-bbc71f7fa3fd\",\"sectionId\":\"a1422391-e2b9-4bc4-907b-371fcea01d70\",\"courseId\":\"e8a65581-ed1c-43f0-90a7-7b9d51b35062\",\"days\":[\"monday\",\"wednesday\",\"friday\"],\"startTm\":\"2019-05-26T09:00:00-04:00\",\"endTm\":\"2021-05-26T09:50:00-04:00\",\"localizations\":[],\"instructionalMethod\":\"Lecture\"}]}]}";
List<String> ids = JsonPath.parse(sectionsData).read(SECTIONS_IDS_JSONPATH);
System.out.println(ids);
}
Alright, since this question might get delete if nothing else ever happens I better post this as an answer.
As explained by Andreas you should use JSONPath $.*[*].instructionEvents[*].sectionId instead. Quoting fromt the comment
The syntax $.[*] is undefined, I can't find any documentation/example
doing that. The JSONPath Online Evaluator [*based on
JSONPath-Plus implemented in JavaScript] treats it as $..[*], but the Java library treats
it differently. Since the outer part of the JSON is {"sections":[ ... ]}, you have an object, so you need a property selector (.prop or
.*). Once you've selected your property (.sections, or .*
since there's only one), the property is an array, so you need an
array selector ([2] or [*]). Hence you can use $.sections[*] or
$.*[*] to match all sections.
Indeed, looking at this massive JSONPath Comparision we can see that the syntax in question is not listed for any implementation.

Rest Assured - comparing the json path with another

I have json for example below
{"TestJson":{
"Result":"Passed",
"description":"Passed."},
"Students":[{
"Class":{
"Primary":"Yes"
},
"Course":{
"Enrolled":"yes",
"AccountNumber":"2387287382"
},
"AccountNumber":"2387287382",
"Paid":"Yes"
}]}
I am wondering how can I find a good solution for this.
What I currently do
.body("Students[0].Course.AccountNumber",equalTo("2387287382"))
.body("Students[0].AccountNumber",equalTo("2387287382"))
My test criteria is to check key Students[0].AccountNumber matches Students[0].Course.AccountNumber
I want to do in this way, but i am not able to find a solution something like
.body("Students[0].Course.AccountNumber",equalTo("Students[0].AccountNumber"))
The above wont work obviously, but that is how I want to compare. basically comparing the key with another key and they should match.
Is this doable?
One way to do it is:
String A =
given ().
when().
get/put/post({api/name})
.extract()
.path("Students[0].Course.AccountNumber");
String B =
given ().
when().
get/put/post({api/name})
.extract()
.path("Students[0].AccountNumber");
Assert.assertEquals(A, B);
Seems like this workaround is the only way to go.
See the Use the response to verify other parts of the response section of the rest-assured docs. You basically want to create a lambda implementing ResponseAwareMatcher<Response>. Something like this:
get("/x").then().body("href", response -> equalTo("http://localhost:8080/" + response.path("userId"));

Categories

Resources