Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

POST request fails (rest-assured test)

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?

like image 639
Purple Avatar asked Aug 13 '15 15:08

Purple


People also ask

How do you assert a Rest assured response?

We can use Assertion in response in Rest Assured. To obtain the Response we need to use the methods - Response. body or Response. getBody.

What is Hamcrest matchers in Rest assured?

Hamcrest Matchers are optional, and are not strictly needed for REST Assured. They allow us to write more expressive unit tests. Gson is automatically used by REST Assured for JSON (de)serialization, as we will see in the examples. Rest Assured can also work with Jackson, if that is available in the classpath.


2 Answers

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:

  1. You're not sending JSON
  2. 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.

like image 179
Johan Avatar answered Sep 18 '22 11:09

Johan


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"));
like image 36
user6506244 Avatar answered Sep 18 '22 11:09

user6506244