I'm using rest-assured and twitter4j for testing twitter API.
All calls are made via RestAssured, twitter4j is used for Json response deserialization.
And what I want to do is to deserialize Json response from twitter - GET statuses/home_timeline which returns Array of Status objects(from twitter4j).
I can easily deserialize one Status object like here:
#Test
public void verifyTwitCreation() {
RequestSpecification spec = new RqBuilder()
.withStatus(textToPublish)
.build();
Response response = twitClient.createTwit(spec);
assertResponseCode(response, 200);
String json = response.getBody().asString();
Status status = null;
try {
status = TwitterObjectFactory.createStatus(json);
} catch (TwitterException e) {
e.printStackTrace();
}
System.out.println(status.toString());
}
But I don't know how to do the same for deserializing array of such Status objects.
Try extracting a list of statuses using JsonPath and then parse them using TwitterObjectFactory:
Response response = twitClient.createTwit(spec);
List<Map<Object, Object>> responseList = response.jsonPath().getList("$");
ObjectMapper mapper = new ObjectMapper();
List<Status> statuses = responseList.stream().map(s -> {
Status status = null;
try {
String json = mapper.writeValueAsString(s)
status = TwitterObjectFactory.createStatus(json);
} catch (TwitterException | IOException e) {
e.printStackTrace();
}
return status;
}).collect(Collectors.toList());
You could move try/catch during parsing to a separate method so it looks nicer:
public class TestClass {
#Test
public void verifyTwitCreation() {
RequestSpecification spec = new RqBuilder()
.withStatus(textToPublish)
.build();
Response response = twitClient.createTwit(spec);
List<Map<Object, Object>> responseList = response.jsonPath().getList("$");
List<Status> statuses = responseList.stream().map(TestClass::createStatus)
.collect(Collectors.toList());
}
private static Status createStatus(Map<Object, Object> jsonMap) {
Status status = null;
ObjectMapper mapper = new ObjectMapper();
try {
String json = mapper.writeValueAsString(jsonMap);
status = TwitterObjectFactory.createStatus(json);
} catch (TwitterException | IOException e) {
e.printStackTrace();
}
return status;
}
}
Update:
Since JsonPath getList() returns list of maps we should convert all maps to JSON string so that it can be used by TwitterObjectFactory. Jackson's ObjectMapper is used in example, but any JSON parsing tool can be used.
I kinda solve my problem. I just generated POJOs from Json with this plugin - https://plugins.jetbrains.com/plugin/8634-robopojogenerator and than mapped Json with rest-assured
List<Status> statuses = Arrays.asList(response.as(Status[].class));
But still I will appreciate the answer for solution with using twitter4j
Related
I am new to testing and i am trying to write a unit test cases on a Flink Datastream which takes input a jsonobject and passes the json object to a processfuntion and it returns a valid or invalid jsonobject when certain rule conditions are met below is the junit test case, below i am trying to compare the output jsonobject from process function with the jsonobject of the input file
#Test
public void testcompareInputAndOutputDataJSONSignal() throws Exception {
org.json.JSONObject jsonObject = toJsonObject();
String input = jsonObject.toString();
String output = JSONDataStreamOutput();
assertEquals(mapper.readTree(input), mapper.readTree(output));
}
below is my toJSONObject and JSONDataStream meathods
public static JSONObject toJsonObject() throws IOException, ParseException {
JSONParser jsonParser = new JSONParser();
FileReader fileReader = new FileReader(getFileFromResources("input.json"));
JSONObject obj = (JSONObject) jsonParser.parse(fileReader);
return obj;
}
public String SignalDataStreamOutput() throws Exception {
final StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
DataStream<JSONObject> validSignal = env.fromElements(toJsonObject())
.process(new JsonFilter());
String outputFolder = "output";
validSignal.writeAsText(outputFolder).setParallelism(1);
env.execute();
String content = new String(Files.readAllBytes(Paths.get("output.txt")));
return content;
}
What i am doing is i am converting a jsonfile to jsonobject using the toJSONObject method and sending to a data stream using SignalDataStreamOutput method which will intern send it to a process function in JsonFilter class and validate it against a set of rules and if it's valid it will return a jsonobject and when trying to access the jsonobject directly from stream i am getting value like org.apache.flink#994jdkeiri so i am trying to write the output to a file and trying to read it back to a string and comparing it in test method but this is a work around process and i found a link to use Mockito framework here i changed it to use json object like below
final Collector<JSONObject> collectorMock = (Collector<JSONObject>)Mockito.mock(JsonFilter.class);
final Context contextMock = Mockito.mock(Context.class);
#Test
public void testcompareInputAndOutputDataForValidSignal() throws Exception {
org.json.JSONObject jsonObject = convertToJsonObject();
Mockito.verify(collectorMock).collect(jsonObject);
}
but the above approach is also not working can you suggest me simplified approach to test the json object
I want my REST API to return a string with the exception details to the client. My client-side code is:
public async Task CreateUnit(UnitEntity unit)
{
try
{
var response = await _http.PostJsonAsync<HttpResponseMessage>("api/units", unit);
}
catch(Exception e)
{
//todo want to display error from the service and carry on
//throw;
}
}
And the code for the service / API is:
[HttpPost]
public HttpResponseMessage CreateUnit(UnitEntity unit)
{
try
{
Dal.CreateUnit(unit);
HttpResponseMessage response = new HttpResponseMessage();
response.StatusCode = HttpStatusCode.Created;
response.Content = new StringContent($"The unit {unit.UnitName} was created successfully");
return response;
}
catch(Exception e)
{
//todo send error message in Http response if possible
//throw;
return new HttpResponseMessage() {StatusCode = HttpStatusCode.NotAcceptable, Content = new StringContent(e.Message)};
}
}
I've tried just returning a string and it basically says that the JSON serialiser can't deserialise it (because it's already a raw string and not JSON). The code above throws an exception:
Deserialization of reference types without parameterless constructor is not supported. Type 'System.Net.Http.HttpContent'
I am learning websockets and my webapp is using jsr 356 library. I followed the tutorials and I can encode/decode POJOs, however I can't find examples on how to serialize either arrays or collections to JSON.
This is what I am doing to encode my data:
#Override
public String encode(ScanPlus scan) throws EncodeException {
JsonObject jsonObject = createJsonObject(scan);
return jsonObject.toString();
}
private JsonObject createJsonObject(ScanPlus scan) {
JsonObject jsonObject = Json.createObjectBuilder()
.add("scan", scan.getCode())
.add("creationdate", String.valueOf(scan.getCreationDate()))
.add("username", scan.getUserName())
.build();
return jsonObject;
}
public String encode(ArrayList<ScanPlus> scans) throws EncodeException {
JsonArrayBuilder jsonArray = Json.createArrayBuilder();
for (ScanPlus scan : scans) {
JsonObject jsonObject = createJsonObject(scan);
jsonArray.add(jsonObject);
}
return jsonArray.toString();
}
This is how I send the data to the encoder:
#OnOpen
public void onOpen(Session session, #PathParam("username") String username) {
...
session.getBasicRemote().sendObject(scans);
}
And this is the exception I am getting:
javax.websocket.EncodeException: No encoder specified for object of class [class java.util.ArrayList]
Could anyone give me a hint on how to do it?
thanks
You need to create Encoder<ArrayList<ScanPlus>>; Encoder<ScanPlus> is not enough..
I have created a rest webservice which has a below code in one method:
#POST
#Path("/validUser")
#Consumes(MediaType.APPLICATION_JSON)
#Produces(MediaType.APPLICATION_JSON)
public JSONObject validUserLogin(#QueryParam(value="userDetails") String userDetails){
JSONObject json = null;
try{
System.out.println("Service running from validUserLogin :"+userDetails);
json = new JSONObject(userDetails);
System.err.println("UserName : "+json.getString("userName")+" password : "+json.getString("password"));
json.put("httpStatus","OK");
return json;
}
catch(JSONException jsonException) {
return json;
}
}
I am using Apache API in the client code.And below client code is calling this service, by posting some user related data to this service:
public static String getUserAvailability(String userName){
JSONObject json=new JSONObject();
try{
HttpContext context = new BasicHttpContext();
HttpClient client = new DefaultHttpClient();
client.getParams().setParameter(ClientPNames.COOKIE_POLICY, CookiePolicy.RFC_2109);
URI uri=new URIBuilder(BASE_URI+PATH_VALID_USER).build();
HttpPost request = new HttpPost(uri);
request.setHeader("Content-Type", "application/json");
json.put("userName", userName);
StringEntity stringEntity = new StringEntity(json.toString());
request.setEntity(stringEntity);
HttpResponse response = client.execute(request,context);
System.err.println("content type : \n"+EntityUtils.toString(response.getEntity()));
}catch(Exception exception){
System.err.println("Client Exception: \n"+exception.getStackTrace());
}
return "OK";
}
The problem is, I am able to call the service, but the parameter I passed in the request to service results in null.
Am I posting the data in a wrong way in the request. Also I want to return some JSON data in the response, but I am not able to get this.
With the help of Zack , some how i was able to resolve the problem,
I used jackson-core jar and changed the service code as below.
#POST
#Path("/validUser")
#Consumes(MediaType.APPLICATION_JSON)
#Produces(MediaType.APPLICATION_JSON)
public JSONObject validUserLogin(String userDetails){
ObjectMapper mapper = new ObjectMapper();
JsonNode node = mapper.readValue(userDetails, JsonNode.class);
System.out.println("Service running from validUserLogin :"+userDetails);
System.out.println(node.get("userName").getTextValue());
//node.("httpStatus","OK");
return Response.ok(true).build();
}
I was using Jersey 1.16 to consume a JSON, but now I'm with difficulties to consume a JSON using Jersey 2.0 (that implements JAX-RS 2.0).
I have a JSON response like this:
{
"id": 105430,
"version": 0,
"cpf": "55443946447",
"email": "maria#teste.br",
"name": "Maria",
}
and the method that consumes it:
public static JSONObject get() {
String url = "http://127.0.0.1:8080/core/api/person";
URI uri = URI.create(url);
final Client client = ClientBuilder.newClient();
WebTarget webTarget = client.target(uri);
Response response = webTarget.request(MediaType.APPLICATION_JSON).get();
if (response.getStatus() == 200) {
return response.readEntity(JSONObject.class);
}
}
I also tried:
return webTarget.request(MediaType.APPLICATION_JSON).get(JSONObject.class);
But the jSONObject return is null. I don't understand my error because the response is OK!
This is how to use the Response type correctly:
private void getRequest() {
Client client = ClientBuilder.newClient();
String url = "http://localhost:8080/api/masterdataattributes";
WebTarget target = client.target(url);
Response res = target
.request(MediaType.APPLICATION_JSON)
.get();
int status = res.getStatus();
String json = res.readEntity(String.class);
System.out.println(String.format("Status: %d, JSON Payload: %s", status, json));
}
If you're just interested in the payload, you could also just issue a get(String.class). But usually you will also want to check the response status, so working with the Response is usually the way to go.
If you want a typed (generic) JSON response, you could also have readEntity return a Map, or a list of Map if the response is an array of objects as in this example:
List<Map<String, Object>> json = res.readEntity(new GenericType<List<Map<String, Object>>>() {});
String id = (String) json.get(0).get("id");
System.out.println(id);
I have found the solution. Maybe it is not the best of, but it works.
public static JsonObject get() {
String url = "http://127.0.0.1:8080/core/api/person";
URI uri = URI.create(url);
final Client client = ClientBuilder.newClient();
WebTarget webTarget = client.target(uri);
Response response = webTarget.request(MediaType.APPLICATION_JSON).get();
//Se Response.Status.OK;
if (response.getStatus() == 200) {
StringReader stringReader = new StringReader(webTarget.request(MediaType.APPLICATION_JSON).get(String.class));
try (JsonReader jsonReader = Json.createReader(stringReader)) {
return jsonReader.readObject();
}
}
return null;
}
I switched the class JSONObject (package import org.codehaus.jettison) by JsonObject (package javax.json) and I used the methods to manipulate the content as String.
S.
mmey answer is the correct and optimal one, instead of invoking the service twice it does it one time.