Rest Assured Framework complete JSON response matching - java

I am using Rest Assured Framework for API testing(Using Java).
At line (1),I am expecting error as there is mismatch in expected JSON response and Actual JSON response
But instead my code is executing successfully.
Can someone please tell me if I am doing anything wrong in below code?
public void test123() {
try {
//Read the Curl Request Input file
String json = input.readFromTextFile(
System.getProperty("user.dir") + "\\src\\test\\resources\\inputFile\\CurlDataFile.txt");
json = json.replaceAll(" ", "");
RestAssured.baseURI = "My URL";
given().
contentType("application/json").
body(json).
when().
post("").
then().
assertThat().body(matchesJsonSchemaInClasspath("testCurlOuput1.json")); (1)
} catch (IOException e) {
e.printStackTrace();
}catch(JsonSchemaValidationException e){
e.printStackTrace();
}
}

This is not directly relevant to REST-assured, but I suggest you take a look at Karate, because IMO it may be exactly what you are looking for.
One of the core features of Karate is that you can perform a full equality match of a JSON payload in one step.
And you can easily use JSON from files, which encourages the re-use of payloads across multiple tests.

You are catching all Exceptions. When your assertThat(..) fails, it throws an Exception. Put a breakpoint on the e.printStackTrace(); run in DEBUG mode and check that your AssertionException/Error isn't being caught.
Instead of catching exceptions, just add all Checked Exceptions to your test signature. If an exception is uncaught, it will fail the test. Alternatively, but less prefered in my opinion, resolve by putting fail(); in the catch block.

Finally I choose different library i.e. jayway.restassured library and then JSON Assert library (org.skyscreamer.jsonassert.JSONAssert) which will comapre actual and expected response.
public void test123() {
String postData = input.readFromTextFile(System.getProperty("user.dir") + "\\src\\test\\resources\\inputFile\\CurlDataFile.txt");
RestAssured.baseURI = "MY URL";
Response r = (Response)given().contentType("application/json").body(postData).when().post("");
String responseBody = r.getBody().asString();
String curlResponse = //I am providing expected Curl response here
//JSON Assertion for matching Expected and Actual response
JSONAssert.assertEquals(curlResponse, responseBody, false);
}
Also sometime we may want to avoid comparing particular field from JSON like some ID field which generate dynamically which we can do using JSON comparator

I am a fan of JSONAssert as this provides easy comparing of complete JSONs.
Just use .extract().response().getBody().asString() to get the string representation of the answer.
Complete example:
#Test
public void getReturnsExpectedDataForMailExampleCom() throws JSONException {
String response = get("/users/mail#example.com")
.then()
.statusCode(200)
.extract().response().getBody().asString();
JSONAssert.assertEquals(
"{\"email\":\"mail#example.com\",\"locale\":\"de-DE\"}",
response,
false);
}
Update The drawback is that the complete JSON is not output to stdout if the assertion fails.

Related

JSON Injection fortify fix in java

I am using the below code for sanitizing the JSON but still, I am getting the JSON injection while scanning from Fortify can you please help me out what is the problem or this is not an issue, maybe suppress. I have also looked out for the same question but those don't solve my problem . my problem is that I am sanitizing my JSON before converting it to java object but still I am getting JSON injection error in fortify
public String handleEventMessage(String jsonRequest) {
MonerisPaymentDetailsObject paymentObject = null;
if(null!=jsonRequest && jsonRequest.length()>0){
try{
paymentObject = mapper.readValue(JsonSanitizer.sanitize(jsonRequest), MonerisPaymentDetailsObject.class);
}catch(Exception ex){
logger.error("Error occured while converting MonerisPaymentDetailsObject json to Object :" , ex);
}
return "abc";
}
Fortify giving below description for this error
1. Data enters a program from an untrusted source.
In this case the data enters at readLine() in EPWFPaymentServicesServlet.java at line 49.
2. The data is written to a JSON stream.
In this case the JSON is written by readValue() in EPWFMonerisPaymentsServiceHandler.java at line 46.
EPWFPaymentServicesServlet.java code where data is entered
#Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
CodeTimer timer = new CodeTimer("EPWFPaymentServicesServlet.doPost()", true);
response.setContentType("text/xml");
BufferedReader reader = new BufferedReader(new InputStreamReader(request.getInputStream()));
StringBuffer requestBuffer = new StringBuffer(request.getContentLength());
String line = null;
while ((line = reader.readLine()) != null) {
requestBuffer.append(line).append('\n');
}
// read the POST request contents
String requestString = requestBuffer.toString();
if (logger.isDebugEnabled()) {
logger.debug("EPWF Payment Service POST Request: \n" + ((requestString == null) ? "Null" : requestString.substring(0, 9)));
}
PaymentServiceHandlerComposit paySvcHandler = new PaymentServiceHandlerComposit();
String responseString =paySvcHandler.handleEventMessage(requestString);//line no 49 where fortify is giving description for class where i am sanitizing the data
if (logger.isDebugEnabled()) {
logger.debug("EPWF Payment Service POST Response: \n" + ((responseString == null) ? "Null" : requestString));
}
response.getOutputStream().print(responseString);
timer.stopAndLogTiming("");
}
Given that you are using a new up-to-date version of jackson, there should be no need to pre-sanitise or alter your data at all before handing it off to jackson.
Jackson will only accept and parse valid JSON, as new exploits and vulnerabilities are discovered, the maintainers of Jackson fix and release new versions. and the best you can do is to keep up to date with these versions.
If the above conditions are met, you can safely suppress this error from fortify, the chance that there is a bug in your custom sanitizer is way higher than the chance of there being one in Jackson

ClassCastException in Mockito

I have the following method for which I'm trying to write unit test using Mockito. I'm fairly new to Mockito and trying to catch up.
Method to test
public synchronized String executeReadRequest(String url) throws Exception{
String result = null;
RestClient client = null;
Resource res = null;
logger.debug("Start executing GET request on "+url);
try{
client = getClient();
res = client.resource(url);
result = res.contentType(this.requestType).accept(this.responseType).get(String.class);
}
catch(Exception ioe){
throw new Exception(ioe.getMessage());
}
finally{
res = null;
client = null;
}
logger.info("GET request execution is over with result : "+result);
return result;
}
The unit test with Mockito
#Test
public void testRestHandler() throws Exception {
RestHandler handler = spy(new RestHandler());
RestClient mockClient = Mockito.mock(RestClient.class,Mockito.RETURNS_DEEP_STUBS);
Resource mockResource = Mockito.mock(Resource.class,Mockito.RETURNS_DEEP_STUBS);
doReturn(mockClient).when(handler).getClient();
Mockito.when(mockClient.resource(Mockito.anyString())).thenReturn(mockResource);
//ClassCastException at the below line
Mockito.when(mockResource.contentType(Mockito.anyString()).accept(Mockito.anyString()).get(Mockito.eq(String.class))).thenReturn("dummy read result");
handler.setRequestType(MediaType.APPLICATION_FORM_URLENCODED);
handler.setResponseType(MediaType.APPLICATION_JSON);
handler.executeReadRequest("abc");
}
But I'm getting a ClassCastException at the line
Mockito.when(mockResource.contentType(Mockito.anyString()).accept(Mockito.anyString()).get(Mockito.eq(String.class))).thenReturn("dummy read result");
Exception
java.lang.ClassCastException: org.mockito.internal.creation.jmock.ClassImposterizer$ClassWithSuperclassToWorkAroundCglibBug$$EnhancerByMockitoWithCGLIB$$4b441c4d cannot be cast to java.lang.String
Appreciate any help to resolve this.
Many thanks.
This style of chaining during stubbing isn't correct:
Mockito.when(
mockResource.contentType(Mockito.anyString())
.accept(Mockito.anyString())
.get(Mockito.eq(String.class)))
.thenReturn("dummy read result");
Even though you've set the mocks to return deep stubs, Matchers work via side-effects, so this line doesn't achieve what you think it does. All three matchers (anyString, anyString, eq) are evaluated during the call to when, and the way you have it your code is likely to throw InvalidUseOfMatchersException at the slightest provocation—including adding unrelated code or verifications later.
This means your problem isn't the use of eq(String.class): It's that Mockito is trying to work the Class matcher in where it doesn't belong.
Instead, you'll need to stub specifically:
Mockito.when(mockResource.contentType(Mockito.anyString()))
.thenReturn(mockResource);
Mockito.when(mockResource.accept(Mockito.anyString()))
.thenReturn(mockResource);
Mockito.when(mockResource.get(Mockito.eq(String.class))) // or any(Class.class)
.thenReturn("dummy read response");
Note that some of the difficulty here is that Apache Wink uses the Builder pattern, which can be laborious in Mockito. (I've returned mockResource here, but you could imagine returning specific other Resource objects, at the expense of requiring them in exactly that order later.) A better way might be to use a default Answer that returns this whenever possible.
Solved it by changing the get call to
get(Mockito.any(Class.class))

Java: Read in JSON file and expose it in a REST service

I am a front-end web developer trying to learn more about the back-end. Currently I just want to read in a local JSON file and expose it in a REST service to be parsed by AngularJS (does that make sense?). I believe I have the servlet set up correctly, but am not sure about how I am approaching this from a Java perspective. It's worth noting that I'm a JavaScript programmer. There are two methods that I am trying to decide between.
The following methods are contained in the class
#Path("/")
public class JsonRESTService {
.....
}
First method
#GET
#Path("/jsonService")
#Consumes("application/json")
#Produces("application/json")
public Response jsonREST(InputStream incomingData) {
StringBuilder jsonBuilder = new StringBuilder();
try {
BufferedReader in = new BufferedReader(new InputStreamReader(incomingData));
String line = null;
while((line = in.readLine()) != null) {
jsonBuilder.append(line);
}
} catch(Exception e) {
System.out.println("Error Parsing: - ");
}
System.out.println("Data Received: " + jsonBuilder.toString());
return Response.status(200).entity(jsonBuilder.toString()).build();
}
Second Method: not sure what to return.
#GET
#Path("/jsonService")
#Consumes("application/json")
#Produces("application/json")
public Response jsonREST(InputStream incomingData) {
JSONParser parser = new JSONParser();
try {
Object obj = parser.parse(new FileReader("C:/files/flat.json"));
JSONObject jsonObject = (JSONObject) obj;
} catch(Exception e) {
e.printStackTrace();
}
}
web.xml servlet mapping
<servlet-mapping>
<servlet-name>javax.ws.rs.core.Application</servlet-name>
<url-pattern>/rest/*</url-pattern>
</servlet-mapping>
So this should be exposed to http://localhost:8080/myapp/rest/jsonService. I got some of this code from a tutorial, but it seems like I want to have a method that returns a JSONObject instead of a Response. Is that correct? Am I on the right track, or is there a really good example of what I am trying to do that I haven't found yet?
There are multiple ways of doing it. You can try this way in the second method
Change the return type to String and return the value of JSONObject as a String using
return jsonObject.toString();
In the client side, Angular JS services - you can convert the String into JSON object through
var obj = JSON.parse(text);
So, now obj is a JSON object which you can use it for further processing.
if you are a JavaScript developer and getting started quickly is the goal, then I would recommend you checkout
http://www.dropwizard.io/getting-started.html
There are a few advantages here
a) much of the server infrastructure stuff is hidden away
b) you can focus on your implementation details
c) no need to figure out how to deploy this etc, it comes with a server built in.
To answer your question about the return type - the server will return javax.​ws.​rs.​core.Response - or some other variation of a Response object. This encapsulates things like HTTP Status codes http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html .
Therefore in order to send a simple response back you may use something like :
return Response.accepted().entity(String.format("{\"JSON\" : \"%s\"}",value)).build();
Replace the string with a JSON string read from file system or generate the JSON from object - what ever your pick of poison is.

Java speech API null response

I am using the java speech recognition API - Jarvis located at https://github.com/lkuza2/java-speech-api
However when I run my application, I get an error : Server returned HTTP response code: 400 for URL: https://www.google.com/speech-api/v1/recognize?xjerr=1&client=chromium&lang=en-US&maxresults=1 (This is the URL that this api uses to get response from Google)
I also created a API key as mentioned in the earlier posts and tried to use the url (this is version 2 API): www.google.com/speech-api/v2/recognize?output=json&lang=en-US&key=MYKey". But in this case I get a null response from Google.
Can anybody please tell me how to get around this?
I change some things from the Recognizer class:
I change the GOOGLE_RECOGNIZER_URL constant to:
private static final String GOOGLE_RECOGNIZER_URL = "https://www.google.com/speech-api/v2/recognize?output=json&lang=en-us&key=YOUR_KEY";
Then I changed this method because the response data have 2 lines
private String rawRequest(File inputFile, int maxResults, int sampleRate) throws IOException
The first line (the one that is read and sent) is null (i don¡t really know why) and the second line has the response of the speech recognized. For this you must read the second line (don't know if there is a nicer way):
String response = br.readLine();
response = br.readLine();
br.close();
return response;
Then I change this method, I think it was using the v1 URL response or something because this method looks for utterance in the json response and there is none utterance key.
private void parseResponse(String rawResponse, GoogleResponse googleResponse)
if (rawResponse == null)
return;
JSONObject jsonObject = new JSONObject(rawResponse);
JSONArray jsonArray= (JSONArray) jsonObject.get("result");
JSONArray jsonArrayResult = (JSONArray) jsonArray.getJSONObject(0).get("alternative");
googleResponse.setResponse(jsonArrayResult.getJSONObject(0).get("transcript").toString());
googleResponse.setConfidence(jsonArrayResult.getJSONObject(0).get("confidence").toString());
I'm new with the json library so it might be a better and shorter way but this worked for me!

Generated web service not receiving parameters

I've generated my web service from WSDL in Netbeans 7.1. For security concerns, I can't show it, but you can safely assume that it's ok, It's been production tested.
I can call the web-service ok. If I make the function return and then dump it, it even returns the correct values. What is wrong though, it never receives any parameters from the SOAP call. This is the way I invoke it in the index.jsp:
try {
Soap.ServiceService service = new Soap.ServiceService();
javax.xml.namespace.QName portQName = new javax.xml.namespace.QName("http://external.example.com/", "ServicePort");
String req = "<getTimestampCount xmlns=\"http://external.example.com/\"><msisdn>656</msisdn></getTimestampCount>";
javax.xml.ws.Dispatch<javax.xml.transform.Source> sourceDispatch = null;
sourceDispatch = service.createDispatch(portQName, javax.xml.transform.Source.class, javax.xml.ws.Service.Mode.PAYLOAD);
javax.xml.transform.Source result = sourceDispatch.invoke(new javax.xml.transform.stream.StreamSource(new java.io.StringReader(req)));
javax.xml.transform.TransformerFactory factory = javax.xml.transform.TransformerFactory.newInstance();
javax.xml.transform.Transformer transformer = factory.newTransformer();
java.io.StringWriter writer = new java.io.StringWriter();
javax.xml.transform.Result stringOut = new javax.xml.transform.stream.StreamResult(writer);
transformer.transform(result, stringOut);
writer.close();
out.print(writer.toString());
} catch (Exception ex) {
out.print(ex.getMessage());
}
And this is the function that returns the result:
public long getTimestampCount(java.lang.String msisdn) throws ParameterException, UnknownException_Exception {
//TODO implement this method
System.out.println(msisdn);
throw new UnsupportedOperationException("Not implemented yet.");
}
The printing always produces null. I can't for the life of me figure out why it's working, finding the right function, but not passing on the values.
Also, I've tested it with this code, and the values returned are correct:
try {
Soap.ServiceService service = new Soap.ServiceService();
Soap.Service port = service.ServicePort();
// TODO initialize WS operation arguments here
java.lang.String msisdn = "5";
// TODO process result here
long result = port.getTimestampCount(msisdn);
out.println("Result = "+result);
} catch (Exception ex) {
out.println(ex.getMessage());
// TODO handle custom exceptions here
}
as expected, this returns a value of 5. This would do fine if I wanted to generate the SOAP response by myself, but I would prefer to receive the response, like the first function does - as SOAP.
Anything else I should post to make this easier? If so, say it, and I'll try to provide everything needed.
I've since solved the problem with these webservices, but I still have no Idea what was wrong with this code.
What I ended up doing, was using the standard syntax, like in the last piece of code. That works perfecty.
Try to add following namespace to your method. It helped me in fixing the same issue.
<tns:getTimestampCount xmlns:tns=\"http://external.example.com/\"><msisdn>656</msisdn>
</tns:getTimestampCount>";

Categories