For some reason, when I try to print the response using print statement for the response body, the system does not print. please help.
In the following API post, I am using Java, rest-assured, TestNG on Eclipse Neon 3. Using #DataProvider annotation, I am passing multiple params in Post request to see the response of the call. Any help would be truly appreciated.
package com.auto.restassured;
import io.restassured.RestAssured;
import static io.restassured.RestAssured.basic;
import static io.restassured.RestAssured.given;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
import io.restassured.response.Response;
import org.apache.log4j.Logger;
import org.apache.log4j.BasicConfigurator;
public class FilePostToVirusTotal {
static String baseURL = "https://www.virustotal.com/vtapi/v2/file/report";
Response myResponse;
#DataProvider(name = "md5hashes")
public String[][] createMd5Hashes() {
return new String[][] {
{"md51", "c1105fb75bc00b5e487f7b26a5be7088"},
{"md52", "213f3287c81d09b095334c9f3151cff8"},
{"md53", "b00c2c458b4cf1eb172e354f54f0fe12"},
{"md54", "32ac9b6b6b7cdbfce179acc5edae98c3"},
{"md55", "510b0b81b85c025d538ed4bad78dc64f"},
};
}
#Test(dataProvider = "md5hashes")
public void md5JsonTest(String apikey, String resource)
{
//Catch API response
myResponse = given().param("text", resource).param("text", "34b937e6e2d28ee6f93a70392d958de8ac4a8dd842e08bbca9bcb0d22f9b9960").when().post(baseURL);
//Print Response
System.out.println(myResponse.getBody().asString());
}
}
You can use built-in log methods e.g. given().log().all() for request and then().log().all() for response
public class Request {
public static void main(String[] args) {
RestAssured.baseURI="http://dummy.restapiexample.com";
given().
//queryParam("key","AIzaSyDIQgAh0B4p0SdyYkyW8tlG-y0yJMfss5Y").
body("{\"name\":\"test111\",\"salary\":\"123\",\"age\":\"23\"}").
when().
post("/api/v1/create").
then().assertThat().statusCode(200).and().contentType(ContentType.JSON).and()
.body("status",equalTo("success")).log().body();
System.out.println("Done");
}
}
Result:
{
"status": "success",
"data": {
"name": "test111",
"salary": "123",
"age": "23",
"id": 65
}
}
Done
Related
I got an exception with validating "status": "OK" in the response body of the DeletePlace request. Request is successful with 200 status code but there is no response body in the log file. Console error is pointing to the Utils line#47. Below is the code & screenshot of the error console pointing error to:
enter image description here
package resources;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintStream;
import java.util.Properties;
import io.restassured.RestAssured;
import io.restassured.builder.RequestSpecBuilder;
import io.restassured.filter.log.RequestLoggingFilter;
import io.restassured.filter.log.ResponseLoggingFilter;
import io.restassured.http.ContentType;
import io.restassured.path.json.JsonPath;
import io.restassured.response.Response;
import io.restassured.specification.RequestSpecification;
public class Utils {
public static RequestSpecification req;
public RequestSpecification requestSpecification() throws IOException
{
if (req==null)
{
PrintStream log = new PrintStream(new FileOutputStream("logging.txt"));
req = new RequestSpecBuilder().setBaseUri(getGlobalValue("baseUrl")).addQueryParam("key", "qaclick123")
.addFilter(RequestLoggingFilter.logRequestTo(log))
.addFilter(ResponseLoggingFilter.logResponseTo(log))
.setContentType(ContentType.JSON).build();
return req;
}
return req;
}
public static String getGlobalValue(String key) throws IOException
{
Properties prop = new Properties();
FileInputStream fis = new FileInputStream("E:\\Eclipse-Workspace\\RestAssuredAPIFramework\\src\\test\\java\\resources\\global.properties");
prop.load(fis);
return prop.getProperty(key);
}
public String getJsonPath(Response response, String key)
{
String resp = response.asString();
JsonPath js = new JsonPath(resp);
return js.get(key).toString(); //Error line
}
}
Please help me out and let me know if any other information is required.
I've tried creating getJsonPath method again and all possible fixes I got from various articles but not able to resolved this. I'm expecting the test to execute without any error.
i recommend you to use org.springframework.core.io.Resource to get your properties, like this :
#Value(value = "classpath:your_file.json")
private Resource resource;
after you got your file, try to mapping with :
public static Map<String, Object> jsonToMap(String json) {
try {
final ObjectMapper mapper = new ObjectMapper();
return mapper.readValue(json, new TypeReference<>(){});
}catch (Exception e) {
e.printStackTrace();
}
return null;
}
I've created a simple Spring Boot app, in which I am trying to consume an API through JSON information. Below you can see the simple code I created using RestTemplate on the Service Class. The problem I am facing is that when I am using the API url below, I am getting the following nested exception.
In case I am using API url with less information, everything works fine. What am I doing wrong?
CONTROLLER CLASS
package com.andrekreou.iot;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
#RestController
public class RestSpringBootController {
private final Service service;
#Autowired
public RestSpringBootController(Service service) {
this.service = service;
}
#GetMapping(path = "/opap")
public List<Object> getWeather(){
return service.getWeather();
}
}
SERVICE CLASS
package com.andrekreou.iot;
import org.springframework.web.client.RestTemplate;
import java.util.Arrays;
import java.util.List;
#org.springframework.stereotype.Service
public class Service {
public List<Object> getWeather(){
String url = "https://api.opap.gr/draws/v3.0/5104/last-result-and-active";
RestTemplate restTemplate = new RestTemplate();
Object[] weather = restTemplate.getForObject(url, Object[].class);
return Arrays.asList(weather);
}
}
The problem is in this line of code:
Object[] weather = restTemplate.getForObject(url, Object[].class);
You're mapping this JSON :
{
"last": {
"gameId": 5104,
"drawId": 2446,
"drawTime": 1653850800000,
"status": "results",
"drawBreak": 1800000,
"visualDraw": 2446,
"pricePoints": {
"amount": 0.5
},
"winningNumbers": {
"list": [
1,
9,
19,
22,
33
],
"bonus": [
1
]
},
...
}
Which is not array, it's an object, and that's why you are getting error described in your question.
Change above line of code to:
Object weather = restTemplate.getForObject(url, Object.class);
and it should work fine.
This is my first time writing code in Java I m running in to JsonParseException when I send invalid json data in my request body. I know I have to catch this error at the point where json body is getting parsed I don't have any idea how it works in my code. It would be great if someone can explain me how to catch the error and send the 400 response instead of the 500 which is being thrown as Uncaught server error and also how the request body is getting parsed.
I m using JAXRS: 2.0.1 and jackson for Json parsing it seems. I also added an exceptionMapper to handle these exceptions but it doesn't seem to work.
//./src/main/java/com.test.rest/Routes.java
package.com.test.rest;
import javax.ws.rs.*;
import javax.ws.rs.core.*;
public class Routes implements Xyz{
#POST
#Path("test")
#Consumes({MediaType.APPLICATION_JSON})
#Produces(MediaType.APPLICATION_JSON)
public Response testJson(#Context HttpHeaders headers, #HeaderParam("abc") String abc, TestRequest request){
if(abc == null){
return Response.status(Response.Status.BAD_REQUEST).entity("Invalid headers").build();
}else{
return Response.status(Response.Status.OK).entity(request.gettestData()).build();
}
}
}
./src/main/java/com.test.rest/TestRequest.java
package.com.test.rest;
public class TestRequest {
private String testData;
public TestRequest () {
}
public TestRequest(String testData){
setTestData(testData);
}
public String gettestData(){
return testData;
}
public void setTestData(String testData){
if(testData!=null){
testData = testData.toLowerCase();
}
this.testData =testData;
}
}
./src/main/java/com.test.rest/JsonParseExceptionMapper.java
package.com.test.rest;
import com.fasterxml.jackson.core.JsonParseException;
import javax.annotation.Priority;
import javax.ws.rs.ext.ExceptionMapper;
import javax.ws.rs.ext.Provider;
import javax.ws.rs.core.*;
#Provider
#Priority(1)
public class JsonParseExceptionMapper implements ExceptionMapper<JsonParseException> {
#Override
public Response toResponse(final JsonParseException exception) {
return Response.status(Response.Status.BAD_REQUEST)
.entity("Cannot parse JSON")
.type(MediaType.TEXT_PLAIN)
.build();
}
}
All the files are in same level and I m using gradle to build my code
this is my request body
{
"testData":
}
//com.fasterxml.jackson.core.JsonParseException: Unexpected character
I have a sample backend response coming as below:
When I try to map this response into the java object, I am getting following error.
com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot deserialize instance of com.mc.membersphere.model.MemberSummaryLabel[] out of START_OBJECT token
Seems like the issue with the body tag coming from API. Which has array of objects. I need help, how to handle this body tag arrays value in Java mapping?
Backend API Response:
{
"body": [{
"pcp": "KASSAM, Far",
"er12M": "0",
"ipAdmits12M": "0",
"ipReAdmits12M": "0",
"rx12M": "0",
"pastMedicalHistory": " ",
"erCost12M": "0.0"
}
]
}
Java Program to get the Rest data into the Java objects is as below.
import java.util.Collections;
import java.util.Properties;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.client.RestTemplate;
import com.mc.membersphere.model.MemberSummaryLabel;
import com.mc.membersphere.utility.PropertyUtil;
public class TestRestclient implements CommandLineRunner{
public static void main(String[] args) {
SpringApplication.run(TestApi.class, args); }
private static Properties prop = PropertyUtil.getProperties();
#Override
public void run(String... args) throws Exception {
RestTemplate restTemplate = new RestTemplate();
HttpHeaders headers = new HttpHeaders();
headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON));
HttpEntity<String> entity = new HttpEntity<String>(headers);
String getMVPSummaryUrl = prop.getProperty("getmvpmembersummary.url");
String url = getMVPSummaryUrl+"/"+"CA";
ResponseEntity<MemberSummaryLabel[]> response = restTemplate.exchange(url, HttpMethod.GET,entity, MemberSummaryLabel[].class);
if(response.getStatusCode()== HttpStatus.OK) {
for(MemberSummaryLabel memberSummaryLabel : response.getBody())
{
System.out.println(memberSummaryLabel.pcp);
}
//System.out.println("Print response" + response);
}
else {
System.out.println("Error");
}
}
}
MemberSummaryLabel is as below.
import com.fasterxml.jackson.annotation.JsonProperty;
public class MemberSummaryLabel {
#JsonProperty("pcp")
public String pcp;
#JsonProperty("er12M")
public Integer er12M;
#JsonProperty("ipAdmits12M")
public Integer ipAdmits12M;
#JsonProperty("ipReAdmits12M")
public Integer ipReAdmits12M;
#JsonProperty("rx12M")
public Integer rx12M;
#JsonProperty("pastMedicalHistory")
public String pastMedicalHistory;
#JsonProperty("erCost12M")
public Double erCost12M;
}
I see, its an issue with your mapping. Your response is in "body" and body contains list of MemberSummaryLabel. So, you need to have one more class as mentioned below,
public class Body{
#JsonProperty("body")
public List<MemberSummaryLabel> memberSummaryLabelList;
}
And your exchange method should return NewClass.
ResponseEntity<Body> response = restTemplate.exchange(url, HttpMethod.GET,entity, Body.class);
And for, iteration use,
for(MemberSummaryLabel memberSummaryLabel : response.getBody().getMemberSummaryLabelList()){
}
This is my method inside my controller which is annotated by #Controller
#RequestMapping(value = "/getServerAlertFilters/{serverName}/", produces = "application/json; charset=utf-8")
#ResponseBody
public JSONObject getServerAlertFilters(#PathVariable String serverName) {
JSONObject json = new JSONObject();
List<FilterVO> filteredAlerts = alertFilterService.getAlertFilters(serverName, "");
JSONArray jsonArray = new JSONArray();
jsonArray.addAll(filteredAlerts);
json.put(SelfServiceConstants.DATA, jsonArray);
return json;
}
I am expecting {"data":[{"useRegEx":"false","hosts":"v2v2v2"}]} as my json.
And this is my JUnit test:
#Test
public final void testAlertFilterView() {
try {
MvcResult result = this.mockMvc.perform(get("/getServerAlertFilters/v2v2v2/").session(session)
.accept("application/json"))
.andDo(print()).andReturn();
String content = result.getResponse().getContentAsString();
LOG.info(content);
} catch (Exception e) {
e.printStackTrace();
}
}
Here is the console output:
MockHttpServletResponse:
Status = 406
Error message = null
Headers = {}
Content type = null
Body =
Forwarded URL = null
Redirected URL = null
Cookies = []
Even result.getResponse().getContentAsString() is an empty string.
Can someone please suggest how to get my JSON in my JUnit test method so that I can complete my test case.
I use TestNG for my unit testing. But in Spring Test Framework they both looks similar. So I believe your test be like below
#Test
public void testAlertFilterView() throws Exception {
this.mockMvc.perform(get("/getServerAlertFilters/v2v2v2/").
.andExpect(status().isOk())
.andExpect(content().json("{'data':[{'useRegEx':'false','hosts':'v2v2v2'}]}"));
}
If you want check check json Key and value you can use jsonpath
.andExpect(jsonPath("$.yourKeyValue", is("WhatYouExpect")));
You might find thatcontent().json() are not solveble please add
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
The 406 Not Acceptable status code means that Spring couldn't convert the object to json. You can either make your controller method return a String and do return json.toString(); or configure your own HandlerMethodReturnValueHandler. Check this similar question Returning JsonObject using #ResponseBody in SpringMVC
You can try the below for get and post methods
#Autowired
private MuffinRepository muffinRepository;
#Test
public void testGetMethod throws Exception(){
Muffin muffin = new Muffin("Butterscotch");
muffin.setId(1L);
BddMockito.given(muffinRepository.findOne(1L)).
willReturn(muffin);
mockMvc.perform(MockMvcRequestBuilders.
get("/muffins/1")).
andExpect(MockMvcResutMatchers.status().isOk()).
andExpect(MockMvcResutMatchers.content().string("{\"id\":1, "flavor":"Butterscotch"}"));
}
//Test to do post operation
#Test
public void testPostMethod throws Exception(){
Muffin muffin = new Muffin("Butterscotch");
muffin.setId(1L);
BddMockito.given(muffinRepository.findOne(1L)).
willReturn(muffin);
mockMvc.perform(MockMvcRequestBuilders.
post("/muffins")
.content(convertObjectToJsonString(muffin))
.contentType(MediaType.APPLICATION_JSON)
.accept(MediaType.APPLICATION_JSON))
.andExpect(MockMvcResutMatchers.status().isCreated())
.andExpect(MockMvcResutMatchers.content().json(convertObjectToJsonString(muffin)));
}
If the response is empty then make sure to override equals() and hashCode() methods on the Entity your repository is working with:
//Converts Object to Json String
private String convertObjectToJsonString(Muffin muffin) throws JsonProcessingException{
ObjectWriter writer = new ObjectWriter().writer().withDefaultPrettyPrinter();
return writer.writeValueAsString(muffin);
}
There are 2 ways to check JSON responses. Lemme guide you through both of them, (taking test method from the question above, and assuming response {"data":[{"useRegEx":"false","hosts":"v2v2v2"}]} as given above)
Method 1) Asserting complete JSON
#Test
public final void testAlertFilterView() {
mockMvc.perform(get("/getServerAlertFilters/v2v2v2/")
.contentType("application/json"))
.andExpect(status().isOk())
// you may even read bigger json responses from file and convert it to string, instead of simply hardcoding it in test class
.andExpect(content().json("{"data":[{"useRegEx":"false","hosts":"v2v2v2"}]}"))
}
Method 2) Asserting specific key-value of response (not writing redundant piece of code)
.andExpect(jsonPath("$.data[0].useRegEx").value(false))
.andExpect(jsonPath("$.data[0].hosts").value("v2v2v2"));
Another thing you might need is the import statement,
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
If you want to check a few values in a specific field of JSON
.andExpect(MockMvcResultMatchers.jsonPath("$.message",
AllOf.allOf(
StringContains.containsString("name: must not be null"),
StringContains.containsString("type: must not be null")
)));
How it looks in the test class. JUnit4.
import com.fasterxml.jackson.databind.ObjectMapper;
import org.hamcrest.core.AllOf;
import org.hamcrest.core.StringContains;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
import org.mockito.junit.MockitoJUnitRunner;
import org.springframework.data.web.PageableHandlerMethodArgumentResolver;
import org.springframework.http.MediaType;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.result.MockMvcResultMatchers;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
#RunWith(MockitoJUnitRunner.class)
public class YourControllerTest {
#Mock
private YourService service;
private MockMvc mvc;
#Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mvc = MockMvcBuilders
.standaloneSetup(new YourController(service))
.setControllerAdvice(new YourExceptionHandler())
.setCustomArgumentResolvers(new PageableHandlerMethodArgumentResolver())
.build();
}
#Test
public void yourControllerMethodName_400_validation() throws Exception {
String path = "/orders/{orderId}/items";
Integer orderId = 123;
YourRequestDto requestDto = YourTestFactory.buildYourRequestDto();
requestDto.setName(null);
requestDto.setType(null);
YourResponseDto expected = YourTestFactory.buildYourResponseDto(requestDto);
Mockito
.when(service.someMethod(orderId, requestDto))
.thenReturn(expected);
mvc
.perform(
MockMvcRequestBuilders.post(path, orderId)
.contentType(MediaType.APPLICATION_JSON)
.content(new ObjectMapper().writeValueAsString(requestDto))
)
.andExpect(MockMvcResultMatchers.status().isBadRequest())
.andExpect(MockMvcResultMatchers.jsonPath("$.message",
AllOf.allOf(
StringContains.containsString("name: must not be null"),
StringContains.containsString("type: must not be null")
)));
}
}