How to cover method inside arrayList in mockito junits - java

I am trying to cover below main class if (!Utility.isEmpty(errors)) block code coverage and i tried below code for adding errors in array List inside client class but still array showing as empty can some one help me to solve this issue.
Main class
public void processDiohShippingMethod(ShippingMethodRequest request) {
List<ResolvableErrorEnum> errors = new ArrayList<>();
checkoutRestClient.updateShippingMethod(request, errors);
if (!Utility.isEmpty(errors)) {
logger.info("ProcessDiohShippingMethod: Shipping method update failure from {} -> {}. Reverting. ",
existingSm, request.getShippingMethodType());
if (existingShippingMethod != null && Constants.RTG_ENJOY.equalsIgnoreCase(existingSm)) {
request.setStartTime(existingShippingMethod.getDropOffShippingInfo().getStartTime());
request.setEndTime(existingShippingMethod.getDropOffShippingInfo().getEndTime());
request.setScheduleType(existingShippingMethod.getDropOffShippingInfo().getCustomerScheduleType());
}
}
}
Client
public void updateShippingMethod(ShippingMethodRequest request, List<ResolvableErrorEnum> errors) {
String url = Utils.formatHttpUrl(url, Cart_Request);
try {
HttpEntity<?> entity = new HttpEntity<>(request);
JsonNode jsonNode = restTemplate.postForObject(url, entity, JsonNode.class);
if (!jsonNode.has(Constants.CONTENT)
|| !jsonNode.path(Constants.CONTENT).path(Constants.ERRORS).isMissingNode()) {
errors.add(ErrorMessages.SM_ERR_01);
return;
}
} catch (HttpClientErrorException e) {
errors.add(ErrorMessages.SM_ERR_01);
} catch (HttpServerErrorException e) {
errors.add(ErrorMessages.SM_ERR_01);
}
}
Test
#Test
public void test_processMethod() throws Exception {
Request req = new Request();
HttpEntity<?> entity = new HttpEntity<>(req);
String jsonResponse = "{\"error\":{\"errorId\":\"1234\",\"message\":\"error message\"}},\"status\":\"success\"}}";
ObjectMapper mapper = new ObjectMapper();
JsonNode actualObj = mapper.readTree(jsonResponse);
when(restTemplate.postForObject("url", entity, JsonNode.class)).thenReturn(actualObj);
ShippingMethodResponse response = helper.processDiohShippingMethod(req);
}

Since you didn't post the whole test code this is just an educated guess, but the most probable cause is that your helper object (the one from the test method) uses a different instance, but not the one you mocked (since I can't see any code in the test, that would set the client).
So a solution could look like this:
#Test
public void test_processMethod() throws Exception {
Request req = new Request();
HttpEntity<?> entity = new HttpEntity<>(req);
String jsonResponse = "{\"error\":{\"errorId\":\"1234\",\"message\":\"error message\"}},\"status\":\"success\"}}";
ObjectMapper mapper = new ObjectMapper();
JsonNode actualObj = mapper.readTree(jsonResponse);
when(restTemplate.postForObject("url", entity, JsonNode.class)).thenReturn(actualObj);
//get this mocked object into the helper object somehow
//otherwhise the mocked method will never be called
helper.setClient(restTemplate);
ShippingMethodResponse response = helper.processDiohShippingMethod(req);
}
You probably assumed the mocking call when(restTemplate.postForObject(...))... to mock the method for all objects of this class. But it will just create a decorator- / wrapper-object arround the object. So you've got to make shure that you call the mocked method on the mocked object, but not on any other object.

Related

can't pass the list json param correctly

I want to use OKHttp3-based RestTemplate to remotely call the interface queryByIds to get basic user information.
#Configuration
public class CloudConfig {
#Bean
public RestTemplate restTemplate() {
return new RestTemplate(new OkHttp3ClientHttpRequestFactory());
}
}
the implementing method queryByIds is below:
#GetMapping("/queryByIds")
public GraceJSONResult queryByIds(#RequestParam String userIds) {
if (StringUtils.isBlank(userIds)) {
return GraceJSONResult.errorCustom(ResponseStatusEnum.USER_NOT_EXIST_ERROR);
}
List<String> userIdList = JsonUtils.jsonToList(userIds, String.class);
ArrayList<AppUserVO> userVOList = new ArrayList<>();
assert userIdList != null;
userIdList.forEach(id -> {
AppUserVO userInfo = getBasicUserInfo(id);
userVOList.add(userInfo);
});
return GraceJSONResult.ok(userVOList);
}
Here is the bussiness code, the http://user.mootalk.com is switched to localhost using SwitchHosts:
// Get the basic information of each user and put it in userVOList
String userServerUrlExecute = "http://user.mootalk.com:8003/user/queryByIds?userIds=" + JsonUtils.objectToJson(publisherIdSet);
System.out.println(userServerUrlExecute);
// the debugger paused
ResponseEntity<GraceJSONResult> entity =
restTemplate.getForEntity(userServerUrlExecute, GraceJSONResult.class);
Here is my util class:
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.util.List;
/**
* json converter
*/
public class JsonUtils {
private static final ObjectMapper MAPPER = new ObjectMapper();
public static String objectToJson(Object data) {
try {
String string = MAPPER.writeValueAsString(data);
return string;
} catch (JsonProcessingException e) {
e.printStackTrace();
}
return null;
}
public static <T> T jsonToPojo(String jsonData, Class<T> beanType) {
try {
T t = MAPPER.readValue(jsonData, beanType);
return t;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
public static <T> List<T> jsonToList(String jsonData, Class<T> beanType) {
JavaType javaType = MAPPER.getTypeFactory().constructParametricType(List.class, beanType);
try {
List<T> list = MAPPER.readValue(jsonData, javaType);
return list;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
When I debug the code ,it didn't go into the queryByIds method, and the console printed the userServerUrlExecute below:
But if you construct a request in Postman like this:
http://user.mootalk.com:8003/user/queryByIds?userIds=210726G71HSY2YY8, it could go into the queryByIds method but the userIdList turned out to be null.
If you construct a request in Postman like this :
http://user.mootalk.com:8003/user/queryByIds?userIds=[\"210726G71HSY2YY8\",\"200628AFYM7AGWPH\"],it works well.
So what's wrong with my code while passing the param?
Later message1:
Now the last construct request did't go into queryByIds both in Chrome's address bar and Postman, it threw a 400 Bad Request;
I replaced #RequestParam with #RequestBody in queryByIds, it still threw a 400 Bad Request
Latter message2:
Now it works...with the same code. This is really a mystery.
Really I wouldn't just pass in JSON into a query parameter like you are doing, it's nasty and doesn't really follow any sort of RESTFUL API standard.
You have 4 options as I see it:
Change to a HTTP POST request and pass in the JSON Data into the request body (Recommend and follows best practise).
If for whatever reasons your requirements are it needs to be a HTTP GET request and needs to be a query parameter then you need to base64 encode the JSON before passing it in.
?userIds=W1wiMjEwNzI2RzcxSFNZMllZOFwiLFwiMjAwNjI4QUZZTTdBR1dQSFwiXQ==
Again if it has to be a HTTP GET request but it doesn't need to be JSON then I would do a comma separated list of IDs into the query parameter
?userIds=210726G71HSY2YY8,200628AFYM7AGWPH
Just request 1 user id at a time.
Your requirements are probably going to be what determines the approach you take.

I cannot send an HTTP request (500 internal server error)

I am currently receiving the following error for the http request am sending. I am trying to send a JSON Array list to trigger a method in the receiving end so as it saves the list in its database.
The 500 Internal Server Error is a very general HTTP status code that means something has gone wrong on the website's server, but the server could not be more specific on what the exact problem is.
Websites phrase 500 errors in many ways but they're all basically saying the same thing: there's a general server issue going on right now.
Most of the time there isn't anything you can do but contact the website directly and then wait on them to fix it.
In the off chance there is a problem on your end, try clearing the cache and deleting any cookies from the site with the error.
Please find the error below:
org.springframework.web.client.HttpServerErrorException: 500 Internal Server
public static String FRONT_URL;
public static String BACK_URL;
public static final String REST_SYNC = "rest/sync";
public static final String REST_API = "rest/api";
private Logger log = Logger.getLogger(FrontSynchronizer.class);
static final Logger synclog = Logger.getLogger("sync");
ResourceBundle rb = ResourceBundle.getBundle("bundles.sync-application-resources", Locale.getDefault());
//method sending the request
public void syncApplications(List<SchemeApplication> accList) {
schemeApplicationDto=new SchemeApplicationDto();
FRONT_URL = rb.getString("sync.front.url").concat(REST_SYNC);
BACK_URL = rb.getString("sync.back.url").concat(REST_API);
JSONArray array = new JSONArray();
if (accList != null && accList.size() > 0) {
for (SchemeApplication student : accList) {
schemeApplicationDto.setId(student.getId());
schemeApplicationDto.setAccountID(student.getAccountID());
schemeApplicationDto.setNoOfPersonsEmployedLocal(student.getNoOfPersonsEmployedLocal());
schemeApplicationDto.setLocalmainclients(student.getLocalmainclients());
JSONObject studentJSON = new JSONObject(schemeApplicationDto);
array.put(studentJSON);
}
}
HttpHeaders headers = new HttpHeaders();
JSONObject object = new JSONObject();
object.put("array", array);
headers.setContentType(MediaType.APPLICATION_JSON);
RestTemplate restTemplate = this.createnewTemplate();
String url = BACK_URL.concat("/application");
HttpEntity<String> requestEntity = new HttpEntity<String>(object.toString(), headers);
ResponseEntity<Boolean> responseEntity = restTemplate.exchange(url, HttpMethod.POST, requestEntity,
Boolean.class);
if (responseEntity.getBody())
{
for(SchemeApplication scheme:accList) {
schemeApplicationService.getDao().delete(scheme);
}
}
}
public RestTemplate createnewTemplate() {
// RestTemplate restTemplate = new RestTemplate(clientHttpRequestFactory());
HttpComponentsClientHttpRequestFactory httpRequestFactory = new HttpComponentsClientHttpRequestFactory();
httpRequestFactory.setConnectTimeout(120000);
RestTemplate restTemplate = new RestTemplate(httpRequestFactory);
return restTemplate;
}
// method that needs to process the request
//The method is trying to send an Array list so as the receiving end can receive the list and save it in its database.
#RequestMapping(value = "application", method = RequestMethod.POST)
public Boolean getAllArchivedpplications(#RequestBody String schemeJson) {
List<SchemeApplication> accList = null;
try {
accList = new ArrayList<SchemeApplication>();
if (StringUtils.isNotEmpty(schemeJson)) {
JSONObject listObject = new JSONObject(schemeJson);
JSONArray entryArray = listObject.getJSONArray("array");
for (int i = 0; i < entryArray.length(); i++) {
JSONObject res = new JSONObject(entryArray.get(i).toString());
ObjectMapper mapper = new ObjectMapper();
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
schemeApplication doc = mapper.readValue(res.toString(),
new TypeReference<schemeApplication>() {
});
accList.add(doc);
}
schemeService.getDao().save(accList); // Service.save accountlist;
}
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
#RequestBody must work on an object.
Standard way to do this kind of work in two ways:
Form a class having class files with same name and structure with your json data you are sending and capture that data in by #RequestBody annotation
As you are sending data as String, send it as request param, and use #RequestParam instead of #RequestBody and parse the way you need to do things. For I think for this kind of arrayList of bulk data you are working with, option 1 will be better/feasible.
For details you can check here: #RequestBody and #ResponseBody annotations in Spring

ResponseBuilder toString() returns object classes in string, not just the raw response string

I'm presently migrating from the Java ASK-SDK v1 to Java ASK SDK v2.
I'm trying to return a webhook call using the ResponseBuilder class that I built my response up and the data is correct, however when I try to populate the HTTP body with the JSON text, the ResponseBuilder.toString() value doesn't just populate the data with just the string, I get the following:
Optional[class Response {
outputSpeech: class SsmlOutputSpeech {
class OutputSpeech {
type: SSML
playBehavior: null
}
ssml: <speak>Some of the things you can say are What would you like to do?</speak>
}
card: null
reprompt: class Reprompt {
outputSpeech: class SsmlOutputSpeech {
class OutputSpeech {
type: SSML
playBehavior: null
}
ssml: <speak>You can say ..., is that what you want?</speak>
}
}
directives: []
shouldEndSession: false
canFulfillIntent: null
}]
Is there another way to get the string for the body of the response? The BaseSkillResponse has a getResponse() call, however, I cannot figure out how to use the class to generate the String response output.
I was able to get the string with the following in my class:
private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
myFunction(){
try{
return toJsonString(responseBuilder.build().get());
} catch(IOException e) {
e.printStackTrace();
}
}
public String toJsonString(Response response)throws IOException {
return OBJECT_MAPPER.writeValueAsString(response);
}
Solve this by doing the following:
public String toJsonString(Response response)throws IOException
{
JacksonSerializer jacksonSerializer = new JacksonSerializer();
constructedResponse = jacksonSerializer.serialize(response);
JSONObject jsonObject = new JSONObject();
jsonObject.put("response",constructedResponse);
}

JavaFX : Supply arguments to Task

I am working on a JavaFX project in which I am making network calls with Task. Unfortunately, I have not been able to find how I can pass arguments to it. I have searched many links, but none of them provides. One link from java2s claims they are passing, but the code does not reflect that.
As you can see from the code below, I am using a for-loop and passing the ID parameter of RestGroupAccount in the URL. This time it's okay because I anyways need all of the RestCanvas.
But I am interested in knowing how to give parameters to Task
Code :
private Task<List<RestCanvas>> fetchCanvases = new Task<List<RestCanvas>>() {
#Override
protected List<RestCanvas> call() throws Exception {
List<RestCanvas> list = new ArrayList<>();
try{
for(RestGroupAccount groupAccount : groupAccounts) {
RestTemplate rest = StaticRestTemplate.getRest();
HttpHeaders requestHeaders = new HttpHeaders();
requestHeaders.add("Cookie", "JSESSIONID=" + StaticRestTemplate.jsessionid);
HttpEntity<RestCanvas> requestEntity = new HttpEntity<>(requestHeaders);
rest.getMessageConverters().add(new MappingJackson2HttpMessageConverter());
rest.getMessageConverters().add(new MappingJackson2HttpMessageConverter());
ResponseEntity<RestCanvas[]> responseEntity = rest.exchange(getCanvasForGroupAccount+groupAccount.getGroupId(), HttpMethod.GET, requestEntity, RestCanvas[].class);
RestCanvas[] restCanvasArray = responseEntity.getBody();
Collections.addAll(list, restCanvasArray);
}
}catch (Exception e){
e.printStackTrace();
}
return list;
}
};
If any more information is required, kindly let me know. Thank you.
I had a similar need, where I needed to create tasks that would take in a File and perform tasks on it. In my case I needed to do different things with files in multiple places, so I created the following class:
public abstract class FileOperationTask<V> extends Task<V> {
protected File file;
public FileOperationTask(File file) {
this.file = file;
}
}
This allows me in my controllers to define the following:
FileOperationTask<List<RaffleTicket>> task = new FileOperationTask<List<RaffleTicket>>(file){
#Override
protected List<RaffleTicket> call() throws Exception {
this.file.toString();
return null;
}
};
new Thread(task).run();
As you can see, I'm able to operate on the File object, and implementing my asynchronous task is now more or less identical to implementing a normal task.
If you need to use the code inside your Task more than once, you should consider creating non-anonymous subclass and instantiate it every time you need it with the construction parameter.
In your example this might be:
private Task<List<RestCanvas>> fetchCanvases = new MyTask(getCanvasForGroupAccount + groupAccount.getGroupId());
// ...
// please don't use this name :)
private static class MyTask extends Task<List<RestCanvas>> {
private final String id;
public MyTask(String id) {
this.id = id;
}
#Override
protected List<RestCanvas> call() throws Exception {
List<RestCanvas> list = new ArrayList<>();
try{
for(RestGroupAccount groupAccount : groupAccounts) {
RestTemplate rest = StaticRestTemplate.getRest();
HttpHeaders requestHeaders = new HttpHeaders();
requestHeaders.add("Cookie", "JSESSIONID=" + StaticRestTemplate.jsessionid);
HttpEntity<RestCanvas> requestEntity = new HttpEntity<>(requestHeaders);
rest.getMessageConverters().add(new MappingJackson2HttpMessageConverter());
rest.getMessageConverters().add(new MappingJackson2HttpMessageConverter());
ResponseEntity<RestCanvas[]> responseEntity = rest.exchange(id, HttpMethod.GET, requestEntity, RestCanvas[].class);
RestCanvas[] restCanvasArray = responseEntity.getBody();
Collections.addAll(list, restCanvasArray);
}
}catch (Exception e){
e.printStackTrace();
}
return list;
}
}

Test POST request on PlayFramework 2.4.x

Good morning,
I'm trying to test some POST requests on my controllers.
I have no problems with GET request :
#Test
public void testGetAll() {
TestModel test = new TestModel();
test.done = true;
test.name = "Pierre";
test.save();
TestModel test2 = new TestModel();
test2.done = true;
test2.name = "Paul";
test2.save();
Result result = new controllers.ressources.TestRessource().get(null);
assertEquals(200, result.status());
assertEquals("text/plain", result.contentType());
assertEquals("utf-8", result.charset());
assertTrue(contentAsString(result).contains("Pierre"));
assertTrue(contentAsString(result).contains("Paul"));
}
But when I have to test a POST request, i can't give POST params to the controller.
here is the method I want to test :
public Result post() {
Map<String, String> params = RequestUtils.convertRequestForJsonDecode(request().queryString());
T model = Json.fromJson(Json.toJson(params), genericType);
model.save();
reponse.setData(model);
return ok(Json.prettyPrint(Json.toJson(reponse)));
}
I've try several solutions, but I can't find a proper one :
Try to use FakeRequest
Try to Mock the Http.Request object
So, what is the best way to write tests for my controllers ?
I'm using Play Framework 2.4.6 with Java.
Junit 4 and Mockito.
For tests of an POST action I use the RequestBuilder and the play.test.Helpers.route method.
For one with JSON data it could look like this (I use Jackson's ObjectMapper for marshaling):
public class MyTests {
protected Application application;
#Before
public void startApp() throws Exception {
ClassLoader classLoader = FakeApplication.class.getClassLoader();
application = new GuiceApplicationBuilder().in(classLoader)
.in(Mode.TEST).build();
Helpers.start(application);
}
#Test
public void myPostActionTest() throws Exception {
JsonNode jsonNode = (new ObjectMapper()).readTree("{ \"someName\": \"sameValue\" }");
RequestBuilder request = new RequestBuilder().method("POST")
.bodyJson(jsonNode)
.uri(controllers.routes.MyController.myAction().url());
Result result = route(request);
assertThat(result.status()).isEqualTo(OK);
}
#After
public void stopApp() throws Exception {
Helpers.stop(application);
}
}

Categories