JUnit for REST: Cannot POST data - java

I want to write a JUnit class for a REST endpoint.
This is my REST method. It works fine.
#POST
#Path("create")
#Produces(APPLICATION_JSON)
public String create(#QueryParam("parentId") String parentId, #QueryParam("name") String name) {
//do sth.
return "{\"status\": \"SUCCESS\"}";
}
Now my JUnit test looks like that, which doesn't work, because I don't know how to POST my data in the right way:
#Test
public void testCreate() {
Client client = ClientBuilder.newClient();
WebTarget wt = client.target(REST_MENU_URL + "create");
String queryParams = "parentId=1&name=NEW_JUnit_NEW";
// In the line below, I want to POST my query parameters, but I do it wrong
Response response = wt.request().post(Entity.entity(queryParams, APPLICATION_JSON), Response.class);
// The response has a 500, because the query parameters are all NULL!
assertEquals("Http code should be 200", 200, response.getStatus());
}
So how do I have to change the line with the 'Response' to make it work?
The problem is, that the query parameters (parentId and name) don't get transmitted (response = wt.request().post(...)).
I tried to POST form parameters too, but no success here either. Just like that:
Form form =new Form().param("parentId", "4").param("name", "NEW_JUnit_NEW");
Response response = wt.request().post(Entity.entity(form, APPLICATION_JSON), Response.class);
Thanks,
Bernhard

Check out the Jersey Client documentation, in particular section 5.3.4 on targeting resources.
Query parameters form a part of the URI of the resource, they're not part of the body of the document posted to the resource. You're seeing null in your resource because you're not filling in the query parameters in the URI, you're posting them as the body. You need to tell Jersey to put them in the URI...
WebTarget wt = client.target(REST_MENU_URL + "create").queryParam("parentId", 1).queryParam("name", "NEW_JUnit_NEW");
You'll also need to ensure that your POST request sets the Accept header to allow application/json (by calling the accept(...) method after calling request()) and you're going to need to construct some kind of Entity to pass to the post(...) method - the problem here is that your resource is not consuming the entity body but the client API expects you to send something - this is a code smell which suggests your API is not particularly ReSTful. You can probably get away with some kind of empty body constructed from an empty string. It should look a bit like this...
Response response = wt.request().accept(MediaType.APPLICATION_JSON).post(Entity.text(""))
Alternatively, you could look into converting your API so that it accepts a JSON document and move the query parameters into that document.

Related

Wiremock encoding issue

I'm currently trying to use wiremock to mock the result of http calls in my unit tests, and when I try to get the response body, I got some encoding issues.
I write one methode to stub a post methode
public static void setupMockExecutionResponse(WireMockServer mockService) throws IOException {
mockService.stubFor(WireMock.post(WireMock.urlEqualTo("/reportExecutions"))
.willReturn(WireMock.aResponse()
.withStatus(HttpStatus.OK.value())
.withHeader("Content-Type", MediaType.APPLICATION_JSON_VALUE+"; charset=utf-8")
.withHeader("set-cookie", "JSESSIONID=1111111111111; SERVERID=jasper")
.withBody(
copyToString(
JasperClientMock.class.getClassLoader().getResourceAsStream("payload/execution-response.json"),
StandardCharsets.UTF_8))));
}
As you can see I specified that the charset of the response body is UTF-8, and in the header I add it too.
The json file used as the response is also encoded in UTF-8
{
"status":"ready",
"totalPages":1,
"requestId":"217f7dc9-47c4-4c44-bada-7e29b653887b",
"reportURI":"/test/test/test/test/export_test",
"exports":[
{
"status":"ready",
"outputResource":{
"contentType":"application/pdf",
"fileName":"export_test.pdf",
"outputFinal":true,
"outputTimestamp":0
},
"id":"6ca0038f-94ff-4bd9-bdf4-6a35259fd05e"
}
]
}
I expect when I make the post request to get the header specified in the setUp of the mock and the json string corresponding at my file.
feign.Response r = jasperFeignClient.executeReport(headerMap, requestBody);
checkResponseStatut(r.status(), EXECUTION_STEP, documentJasperRequest.getUrlReport(), requestBody);
getCookie(r, cookies);
String execResponse = IOUtils.toString(r.body().asInputStream(), String.valueOf(StandardCharsets.UTF_8));
I have the good return code (200), the cookies that I set, but my response body is messed up and look like this
So when I try to convert it to a java object I have parsing error, because it can't find the begining character of the json.
I even tryed to hard code the json string directly in the body of the stub, but that didn't change a things.
EDIT
When I make a direct call to the stubbed endpoint in my test, the encoding is good
#Test
public void testGetPDF(){
Response response = given().when().post("http://localhost:9561/reportExecutions");
String status = response.jsonPath().get("status");
System.out.println(status);
assertEquals(status, "ready");
}
It's only when I go into the class where the call is made that i got encoding issues.
It looks like your call via the Jasper client is by default setting accept-encodig:gzip (or something similar) and WireMock is therefore returning a gzipped body.
You should be able to resolve the issue by doing one of: a) disabling gzip in WireMock, b) disabling gzip in your client config, or c) ungzipping the body before attempting to parse it.
After updating all my pom dependencies to their latest version solved this encoding issue.

Test REST API using Rest Assured Get type returning 400 status code

I'm able to test my REST API through postman client and its giving me the expected response. But, when I try to test through junit, its giving 400 status code
Content type is application/json as per the payload
final static String ROOT_URI = "http://localhost:7000/employees";
#Test
public void simple_get_test() {
Response response = get(ROOT_URI + "/list?emp=100");
}
Am I missing anything
Try setting the port using RestAssured.port = 7000 and remove it from the URI. It would be usefull if you post the response message aside from the code.

Java Rest Assured is over processing my get request

I am trying to connect to a REST API (Not my own so I can't fix their issues) but when I send a GET request, Rest Assured is reprocessing my URI causing the call to fail.
Here is the code to build the request:
Call rest = new Call("https://rest.test.com"); // Custom class to simplify REST calls.
JSONObject searchCriteria = new JSONObject();
searchCriteria.put("textSearchType", "SEARCHNAME");
searchCriteria.put("textSearchString", "joe blow");
String header = "Lead Inline Quick Search";
StringBuilder resource = new StringBuilder("/api/v1/search?");
resource.append("searchCriteria=")
.append(URLEncoder.encode(searchCriteria.toString()))
.append("&header=")
.append(URLEncoder.encode(header));
System.out.println("REST call: " + resource.toString());
rest.get(resource.toString(), 200); // Perform a get on the query, expect a 200 response
When I look at the output, the request is correct:
REST call: /api/v1/search?searchCriteria=%7B%22textSearchString%22%3A%22joe+blow%22%2C%22textSearchType%22%3A%22SEARCHNAME%22%7D&header=Lead+Inline+Quick+Search
However when I look at the debug for Rest Assured, it reprocesses the request causing the call to fail:
Request method: GET
Request URI: https://rest.test.com/api/v1/search?searchCriteria=%257B%2522textSearchString%2522%253A%2522joe%2Bblow%2522%252C%2522textSearchType%2522%253A%2522SEARCHNAME%2522%257D&header=Lead%2BInline%2BQuick%2BSearch
Note:
'{' is correctly converted to '%7B' from the Net encoding and looks right in the resource, but Rest Assured then further converts all the '%' to '%25' making the json invalid ({ becomes %257B).
The '+' in the header is converted to '%20' for some reason. While technically the same, there is no reason to "fix" it.
If I don't encode the values when building the resource, the get call fails because it sees the spaces.
IllegalArgumentException-Invalid number of path parameters. Expected 1, was 0. Undefined path parameters are: "textSearchString":"joe blow","textSearchType":"SEARCHNAME".
So what is the proper way to encode the values? Or get Rest Assured not to monkey with the string it's sent?
The comment from #Hypino put me on the right track.
Adding .urlEncodingEnabled(false) to the .given() did not change the results (call was still double processed). But adding .setUrlEncodingEnabled(false) to the RequestSpecBuilder() gave the correct results.
private RequestSpecBuilder build = new RequestSpecBuilder().setUrlEncodingEnabled(false);
The logged call and the actual call are now the same:
REST call: /api/v1/search?searchCriteria=%7B%22textSearchString%22%3A%22joe+blow%22%2C%22textSearchType%22%3A%22SEARCHNAME%22%7D&header=Lead+Inline+Quick+Search
Request method: GET
Request URI: https://rest.test.com/api/v1/search?searchCriteria=%7B%22textSearchString%22%3A%22joe+blow%22%2C%22textSearchType%22%3A%22SEARCHNAME%22%7D&header=Lead+Inline+Quick+Search

JSON POST using RestAssured

I am trying to create a test to validate the response of a JSON Post is as expected.
I am trying to test the POST of a JSON message body to a URL which is turn then sends a text message and if successful it sends a response that it was successful again in JSON format.
My test is as follows
public void simpleTest() {
String myJson = "{\"phoneNumber\":\"353837986524\", \"messageContent\":\"test\"}";
given()
.port(31111) // port number
.header("Content-Type", "application/json")
.body(myJson)
.when()
.post("/testenvironment/text/send")
.then().assertThat()
.body("message", equalTo("{\"resultMessage\":\"Message accepted\"}"));
}
But seem to be getting this exception
java.lang.IllegalStateException: You can either send form parameters
OR body content in POST, not both!
And I'm not sure what the issue is?
Restassured is failing to parse Json as per the stack trace. I use org.json jar, which is more elegant way to handle big json inputs. There are other implementations of json handling in java, which can be used based on your preference.
Coming to your code:
public void simpleTest() {
// use org.json JSONObject to define your json
JSONObject jsonObj = new JSONObject()
.put("phoneNumber","353837986524")
.put("messageContent","test");
given()
.port(31111) // port number
.contentType("application/json") //another way to specify content type
.body(jsonObj.toString()) // use jsonObj toString method
.when()
.post("/testenvironment/text/send")
.then()
.assertThat()
.body("message", equalTo("{\"resultMessage\":\"Message accepted\"}"));
}
Also, I didnt find what the output of the rest service in the question. For example it is returning a a json {"resultMessage":"Message accepted"} you should be validating the response in the following way:
...
.body("resultMessage",equalTo("Message accepted"));
Try changing the mimeType to a header instead of a parameter.
And based on the information you shared I think what you need is the Content-Type header, not mimeType.

Error while calling RESTful Web-Service using Jersey Client POST method

Getting an error while trying to consume a Restful web service using
POST method(with form param).
I want to consume a REST application using POST method.
Please find below the resource class I want to access.
#Path("/user")
public class User {
#POST
#Consumes(MediaType.APPLICATION_FORM_URLENCODED)
public Response get(#FormParam("username") String userName,
#FormParam("userid") String userId ){
}
I tried using Jesry Client for accessing.Please find below the code i tried.
I tried adding values to FormParam as shown below.
Trail 1
WebResource webResource = client.resource("baseURL/user");
String input = "userid:1001,username:demo1";
ClientResponse response = webResource.type("application/x-www-form-urlencoded").post(ClientResponse.class, input);
I am getting a an error response back "The server encountered an internal error () that prevented it from fulfilling this request".
I think I am not adding the values to FormParam properly.
Trial 2
I also tried adding the form params using the below code
MultivaluedMap formData = new MultivaluedMapImpl();
formData.add("userid", "1001");
formData.add("username", "demo1");
ClientResponse response = webResource.type("application/x-www-form-urlencoded").post(ClientResponse.class, formData);
This also resulted in the same error.
Trial 3
Form f = new Form();
f.add("userid", "1001D");
f.add("username", "1001D");
ClientResponse response = webResource.type(MediaType.APPLICATION_FORM_URLENCODED_TYPE).post(ClientResponse.class, f);
This also resulted in the same error.
Any help is appreciated.
Since your error indicates "Server encountered an internal error" you need to look at the server (logs) to see what went wrong. Certainly your 3rd client looks fine to reach the service you defined (assuming you are using something real instead of the string "baseURL").
You can easily test your server is working separately from your client by creating a HTML page to reach the service. Create a HTML form using enctype="application/x-www-form-urlencoded" and posting to your service endpoint (what you are calling "baseURL/user") with form parameters userid and username. When you view the HTML form in a browser and hit the submit button, it will call your server - if you get the same error you can be sure it is nothing to do with your client code.
Hope http://yogeshmprajapati.blogspot.in/2011/12/login-to-fb-from-java.html will help you.

Categories