JsonPaths can't reference an object
Bug report:
I'm using spring cloud contract version 2.0.2.RELEASE and when I'm generating code with the following contracts I'm getting 2 errors:
- The
JSONArrayimport is missing in the test class - The syntax
isEqualTo(["Exit Counseling","Groovy Script","Groovy Script"]);is invalid in java
The java compiler complains with the following error:
illegal start of expression
';' expected
Please find below the contract and generated source code.
Thanks for help.
Contract:
description: some queries
request:
url: /pendingFiles
queryParameters:
page: 0
size: 10
method: GET
headers:
Content-Type: application/json
response:
status: 200
headers:
Content-Type: application/json;charset=UTF-8
body:
- workbookType: Exit Counseling
username: John
filename: 04_a_EXIT_COUNSELING.csv
uploadedDate: '2018-11-07T16:51:28.000Z'
- workbookType: Groovy Script
username: John
filename: exitConseling/triggerGraduating.groovy
uploadedDate: '2018-11-07T16:51:28.000Z'
- workbookType: Groovy Script
username: John
filename: exitConseling/triggerWithdrawn.groovy
uploadedDate: '2018-11-07T16:51:28.000Z'
matchers:
body:
- path: $..workbookType
type: by_equality
- path: $..username
type: by_equality
- path: $..filename
type: by_equality
- path: $..uploadedDate
type: by_equality
Generated Test:
@Test
public void validate_shouldGetTheListOfPendingFiles() throws Exception {
// given:
RequestSpecification request = given()
.header("Content-Type", "application/json");
// when:
Response response = given().spec(request)
.queryParam("page","0")
.queryParam("size","10")
.get("/pendingFiles");
// then:
assertThat(response.statusCode()).isEqualTo(200);
assertThat(response.header("Content-Type")).isEqualTo("application/json;charset=UTF-8");
// and:
DocumentContext parsedJson = JsonPath.parse(response.getBody().asString());
assertThatJson(parsedJson).array().isEmpty();
// and:
assertThat(parsedJson.read("$..workbookType", JSONArray.class)).isEqualTo(["Exit Counseling","Groovy Script","Groovy Script"]);
assertThat(parsedJson.read("$..username", JSONArray.class)).isEqualTo(["John","John","John"]);
assertThat(parsedJson.read("$..filename", JSONArray.class)).isEqualTo(["04_a_EXIT_COUNSELING.csv","exitConseling\/triggerGraduating.groovy","exitConseling\/triggerWithdrawn.groovy"]);
assertThat(parsedJson.read("$..uploadedDate", JSONArray.class)).isEqualTo(["2018-11-07T16:51:28.000Z","2018-11-07T16:51:28.000Z","2018-11-07T16:51:28.000Z"]);
}
Duplicate of https://github.com/spring-cloud/spring-cloud-contract/issues/363
You can't do it at the moment (reference an object, instead of a primitive). You can, however, call execute() to use a method
Actually, it's not a duplicate of that one but it's related. I'll rename this issue and leave it as an enhancement
Thanks @marcingrzejszczak for looking so quickly at this report :)
In your new title you're saying "can't reference an object", does it mean that this could work if what I was referencing was say an int ?
Just so you know I did try the following contract to check that and it does generate the same error code.
Contract:
description: |
Stuff
request:
url: /some
queryParameters:
page: 0
size: 10
method: GET
headers:
Content-Type: application/json
response:
status: 200
headers:
Content-Type: application/json;charset=UTF-8
body:
- anInt: 1
aDouble: 1.1
- anInt: 2
aDouble: 2.1
- anInt: 3
aDouble: 3.1
# Those matchers are necessary for the code generator, otherwise the server tests won't work
matchers:
body:
- path: $..anInt
type: by_equality
- path: $..aDouble
type: by_equality
Generated Test:
@Test
public void validate_test() throws Exception {
// given:
RequestSpecification request = given()
.header("Content-Type", "application/json");
// when:
Response response = given().spec(request)
.queryParam("page","0")
.queryParam("size","10")
.get("/some");
// then:
assertThat(response.statusCode()).isEqualTo(200);
assertThat(response.header("Content-Type")).isEqualTo("application/json;charset=UTF-8");
// and:
DocumentContext parsedJson = JsonPath.parse(response.getBody().asString());
assertThatJson(parsedJson).array().isEmpty();
// and:
assertThat(parsedJson.read("$..anInt", JSONArray.class)).isEqualTo([1,2,3]);
assertThat(parsedJson.read("$..aDouble", JSONArray.class)).isEqualTo([1.1,2.1,3.1]);
}
The generator could instead generate an array on the fly like that:
assertThat(parsedJson.read("$..anInt", JSONArray.class)).isEqualTo(new int[] {1,2,3});
assertThat(parsedJson.read("$..aDouble", JSONArray.class)).isEqualTo(new double[] {1.1,2.1,3.1});
and then the missing import to org.json.JSONArray could be worked around with a change to the maven plugin configuration:
<plugin>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-contract-maven-plugin</artifactId>
<configuration>
<imports>
<import>org.json.JSONArray</import>
</imports>
</configuration>
</plugin>
I'm not sure where the code is generated in the plugin, but if you have some indication I could try to give it a look ;)
@marcingrzejszczak It is really very strange that full body fromRequest().body() can be returned as json string with escaped symbols, and fromRequest().body('some.path') generate test class as not string, so test class can not be compiled