POST request fails (rest-assured test) - java

I have problem with making POST request with rest-assured.
This code works:
given().contentType(ContentType.JSON).body("{\"key\": \"val\"}").
when().post(url + resource).then().assertThat().statusCode(200).body("otherVal", equalTo(otherVal));
But I was trying to use param() or parameter() methods like that:
This one gives:
given().parameter("key", "val").
when().post(url + resource).then().assertThat().statusCode(200);
Expected status code <200> doesn't match actual status code <415>.
This:
given().parameter("key", "val").
when().post(url + resource).then().assertThat().body("otherVal", equalTo(otherVal));
java.lang.IllegalStateException: Expected response body to be verified as JSON, HTML or XML but no content-type was defined in the response.
Try registering a default parser using:
RestAssured.defaultParser(<parser type>);
And This:
RestAssured.defaultParser = Parser.JSON;
given().parameter("key", "val").
when().post(url + resource).then().assertThat().body("otherVal", equalTo(otherVal));
java.lang.IllegalArgumentException: The JSON input text should neither be null nor empty
I have run out of ideas whats wrong.
What I'm trying to do is to avoid writing full jsons for all test, it will be faster if I could skip all "" and {}.
Is my approach correct?

Let's look at your first example:
given().contentType(ContentType.JSON).body("{\"key\": \"val\"}").
when().post(url + resource).then().assertThat().statusCode(200).body("otherVal", equalTo(otherVal));
What happens here is that you put { "key" : "val" } (as text) into the body of the request. This text happens to be JSON. From REST Assured's perspective you might as well could have put { "key" : "val" which is not valid JSON. Your server responds correctly since the server requires and understands JSON. It understands that the body should be JSON since you passing JSON as content-type.
So let's look at your second example:
given().parameter("key", "val").
when().post(url + resource).then().assertThat().statusCode(200);
Here your service returns 415 because you're missing the JSON content-type. What happens when you use param or parameter with POST is that you create form parameters. Form parameters are also sent in the request body BUT form parameters are not JSON! Specifying "key" and "val" as form parameter like you do will be the same as this:
given().contentType("x-www-form-urlencoded").body("key=val").when().url + resource).then().assertThat().statusCode(200);
So in your second example there's actually two problems:
You're not sending JSON
You have the wrong content-type
And because of (2) you get 415 from the server
Moving on to your third example:
given().parameter("key", "val").
when().post(url + resource).then().assertThat().body("otherVal", equalTo(otherVal));
What (probably) happens here is that your server doesn't contain a response body because it expects the request to include "application/json" as content-type. So there is no body to assert (the request is wrong)! The response only contains the 415 status (line) as a header.
Which leads us to your last example:
RestAssured.defaultParser = Parser.JSON;
given().parameter("key", "val").
when().post(url + resource).then().assertThat().body("otherVal", equalTo(otherVal));
Here you instruct REST Assured to treat a missing content-type as JSON but the problem (again) is that your server doesn't return any response body at all so this won't help.
Solution:
You should put a supported JSON object-mapping framework (Jackson, Faster Jackson, Simple JSON or Gson) in your classpath (for example jackson-databind) and just create a map as described in the documentation:
Map<String, Object> jsonAsMap = new HashMap<>();
map.put("key", "val");
given().
contentType(ContentType.JSON).
body(jsonAsMap).
when().
post(url + resource).
then().
statusCode(200).
body("otherVal", equalTo(otherVal));
Since creating maps in Java is quite verbose I usually do something like this if I have nested maps:
given().
contentType(ContentType.JSON).
body(new HashMap<String,Object>() {{
put("key1, "val1");
put("key2, "val2");
put("key3", asList("val3", "val4"));
put("nested", new HashMap<String,String>() {{
put("key4", "val4");
put("key5", "val5");
}});
}}).
when().
post(url + resource).
then().
statusCode(200).
body("otherVal", equalTo(otherVal));
Or you create a DTO representation of your data and just pass an object to REST Assured:
MyDTO myDTO = new MyDTO(...);
given().
contentType(ContentType.JSON).
body(myDTO).
when().
post(url + resource).
then().
statusCode(200).
body("otherVal", equalTo(otherVal));
You can read more in the object-mapping documentation.

I was looking for answer and I figured it out too ..
add a file to your src/test/resouces folder and add this code to your test . Should be all good
URL file = Resources.getResource("ModyNewFieldsReq.json");
String myRequest = Resources.toString(file,Charsets.UTF_8);
Response fieldResponse = given ()
.header("Authorization", AuthrztionValue)
.header("X-App-Client-Id", XappClintIDvalue)
.contentType("application/vnd.api+json")
.body(myRequest).with()
.when()
.post(dataPostUrl)
.then()
.assertThat()
.log().ifError()
.statusCode(200)
.extract().response();
Assert.assertFalse(fieldResponse.asString().contains("isError"));

Related

how to send the data in request body as json to resttemplate.exchange

Assume I am getting the values from one API, need to send that data to other API through resttemplate.exchange
I am iterating the values like below
String Data="";
for(String value: receivedvalues){
Data=Data.concat(","+val)
}
List<map> result=resttemplate.exchange(url+Data,HttpMethod.GET,ArrayList.class).getBody);
The above problem is I'm adding data to request url, but i need to send through the request body but in this case how we can send data through the resttemplate.exchange.Can any one have any idea on this.
Thanks in advance.
Map your JSON object to POJO class and then use RestTemplate.exchange(...) method.
Usage example:
ReceivedValuesClass receivedValuesPojo = mapJson(receivedValues);
RequestEntity request = RequestEntity
.get(new URI(url))
.accept(MediaType.APPLICATION_JSON)
.body(receivedValuesPojo);
ResponseClass result=resttemplate.exchange(url,HttpMethod.GET,ResponseClass.class).getBody;
More information here: https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/web/client/RestTemplate.html#exchange-org.springframework.http.RequestEntity-java.lang.Class-

Rest assured, how to extract generated token from response body after POST request and set it to header

Performing any request, I need to perform Authentication with POST request with body {username:"somename", password:"somepass"},
header Content-Type:application.json which gives me a response with generated token, which I need to paste as a second header, smth like Authorization:generated-tokenkjhsdkjfvjbwjbQ== for further requests.
Could you help me with it, please.
Variant which worked for me:
String token = given()
.contentType("application/json")
.body(new User("someuser" , "123"))
.when()
.post(RestConfig.baseUrl+"/authentication-url")
.then().extract().response().as(TokenResponse.class).getToken();
given()
.contentType("application/json")
.header("Authorization", token)
.get(RestConfig.baseUrl+"/some-path")
.then()
.statusCode(200)...
I had a similar requirement, where I had to pass the auth token back and forth, but this was spring rest template not rest assured. For that purpose, I used client filter, which captured the token on response and set it as a header on request. You can search if there is something similar in rest assured, which can do the job.
Here is a sample, https://github.com/rest-assured/rest-assured/wiki/Usage
Custom Authentication
Rest Assured allows you to create custom authentication providers. You do this by implementing the io.restassured.spi.AuthFilter interface (preferably) and apply it as a filter. For example let's say that your security consists of adding together two headers together in a new header called "AUTH" (this is of course not secure). Then you can do that like this (Java 8 syntax):
given().
filter((requestSpec, responseSpec, ctx) -> {
String header1 = requestSpec.getHeaders().getValue("header1");
String header2 = requestSpec.getHeaders().getValue("header2");
requestSpec.header("AUTH", header1 + header2);
return ctx.next(requestSpec, responseSpec);
}).
when().
get("/customAuth").
then().
statusCode(200);
The reason why you want to use a AuthFilter and not Filter is that AuthFilters are automatically removed when doing given().auth().none(). ...
I could be misunderstanding the question, but from what I am getting from it, I think something like this should work:
String token =
given().
header("Content-Type", "application/json").
body(/* body content goes here */).
when().
post(/* route goes here */).
then().
extract().path("token").toString()
// the above path arg depends on the response you get from the call.
Then the next call would be something like:
given().
header("Content-Type", "application/json").
header("Authorization", token).
when()...etc.
Some of the specifics will depend on the API, but I use this format all the time. Often getting a response of a user ID, or a token, etc. and using it for future calls.
More info on extracting in the rest assured docs: https://github.com/rest-assured/rest-assured/wiki/Usage#extracting-values-from-the-response-after-validation
If you want to extract one parameter from response then this should work:
String jsonBody= ( enter request payload here )
ValidatableResponse response = RestAssured.given().baseUri(baseURL)
.accept("application/json")
.header("Content-Type","application/json")
.body(jsonBody).when().post("/auth")
.then().assertThat().statusCode(200)
.log().all();
String token=response.extract().path("token");

Process Post response in Play Framework

I'm at a loss for how to process results from a post in play framework. The following code works to process a GET response:
WSRequestHolder request = WS.url(myURL);
return async(
request.get().map(
new Function<WS.Response, Result>() {
public Result apply(WS.Response response) {
String json = response.getBody();
System.out.println("Json response: " + json);
//Do stuff
return ok(json);
}
}
)
);
I thought I'd just be able to replace .get() with post(myvalue). However, this does not work. What is the proper way to process a POST response in Play Framework?
WSRequestHolder.post(...) accepts 4 different types as a parameter: java.io.File, java.io.InputStream, JsonNode and String. You can replace .get() with .post(myvalue), depending on what myvalue is and what Content-Type myURL is expecting.
POSTing with those types will set the Content-Type header appropriate to the type. Passing a JsonNode will automatically set the Content-Type to application/json, for example. However, when passing a String you will likely have to set the Content-Type yourself, as Play isn't going to know whether that String is supposed to be JSON or a form.
From the Play Documentation:
If you're sending a form:
request.setContentType("application/x-www-form-urlencoded").post("key1=value1&key2=value2") ...
Or posting JSON as a String:
request.setContentType("application/json").post(jsonString) ...
If you're having other compile errors, please post them.

How to parse RequestBody in Play Framework (Java)

I need to parse the RequestBody of a POST, currently I am doing the following:
public static Result createMessages(){
RequestBody body = request().body();
return ok("Got body: " + body);
}
This results in the following being returned to the browser:
Got body: DefaultRequestBody(None,None,None,None,None,Some(MultipartFormData(Map(from -> List(Hello), message -> List(World), subject -> List(Test)),List(),List(),List())),false)
I need to get the MultipartFormData from this output as you can see it has the posted values, but unsure how to do this in Java Play
Handling multipart forms is nice documented at Play's docs
For other form fields you can easily use ie. DynamicForm

How to read data in response of POST operation using jersey client (RestFull)

In my java client application, I am accessing a endpoint URL and could able to get response back, but it is in HTML code!.
Method : Post
resource.accept(MediaType.APPLICATION_JSON_TYPE);
WebResource resource = Client.create().resource(
communicatorVO.getTargetURL());
String **response** = resource.queryParams(communicatorVO.getFormData()).type(MediaType.APPLICATION_JSON_TYPE).post(String.class, gson.toJson(communicatorVO.getRequestObject()));
The response object always contains HTML code! How to get the actual data?
If I try using chrome restful client, am getting below response.
{
"access_token" : "YOUR_NEW_ACCESS_TOKEN",
"token_type" : "bearer",
"expires_in" : 10800,
"refresh_token" : "YOUR_REFRESH_TOKEN",
"scope" : "write read offline_access"
}
This issue has been resolved.
I added type & accept in single line and it started returning expected json response. Now I can parse the json into any java object.
Code :
response = resource.type(MediaType.APPLICATION_FORM_URLENCODED_TYPE).accept(MediaType.APPLICATION_JSON_TYPE).post(ClientResponse.class, communicatorVO.getFormData());;

Categories

Resources