I'm using Powermock to mock local variable "response" in sendAddTaskResult method.
public void sendAddTaskResult() {
//....
HttpResponse response
= request.header("Authorization", "Token " + token).fields(parameters).asJson();
//....
}
this is my mocking code:
HttpResponse httpResponse=mock(HttpResponse.class);
when(httpResponse.getStatus()).thenReturn(200);
whenNew(HttpResponse.class).withAnyArguments().thenReturn(httpResponse);
It seems doesn't work, I wish someone would help me,Thanks!
Thanks for mksmanjit's answer, I tried to mock HttpResponse, and use Powermock "whenNew" method to mock HttpRequestWithBody, but it seems my mock "HttpRequestWithBody" doesn't work properly. It can't work during create HttpRequestWithBody object...
//mock HttpResponse
HttpResponse httpResponse = mock(HttpResponse.class);
when(httpResponse.getStatus()).thenReturn(200);
//mock HttpRequestWithBody
HttpRequestWithBody httpRequestWithBody =mock(HttpRequestWithBody.class);
when(httpRequestWithBody.header(Mockito.anyString(), Mockito.anyString())).thenReturn(httpRequestWithBody);
when(httpRequestWithBody.header(Mockito.anyString(), Mockito.anyString()).fields(anyParameters())).thenReturn(mock(MultipartBody.class));
when(httpRequestWithBody.header(Mockito.anyString(),Mockito.anyString()).fields(anyParameters()).asJson()).thenReturn(httpResponse);
// mock new local variable
whenNew(HttpRequestWithBody.class).withAnyArguments().thenReturn(httpRequestWithBody);
private static Map<String, Object> anyParameters() {
return Mockito.any();
}
Related
In a class I'm testing, there is a private method that instantiates the GetRequest class in Unirest. How do I use Mockito so that the instantiation of GetRequest class in getResponse() results in a mock object that I use in my JUnit test?
public ClassUnderTest {
public String methodToTest() {
String url = "http://localhost:8080";
String result = getResponse(url);
return result;
}
private String getResponse(String url) {
GetRequest getRequest = new GetRequest(HttpMethod.GET, url);
... = getRequest.header(...).headers(...).asJson();
...etc...
}
}
Thank you,
Rico
One solution is to use a partial mock as in Use Mockito to mock some methods but not others. I can refactor the call to the constructor in a private method and mock that.
I have the following situation:
My REST API one:
#RestController
#RequestMapping("/controller1")
Public Class Controller1{
#RequestMapping(method = RequestMethod.POST)
public void process(#RequestBody String jsonString) throws InterruptedException, ExecutionException
{
............
}
}
JSON POST request, request1, for the REST API(Controller1):
{
"key1":"value1",
"key2":"value2"
}
My REST API two:
#RestController
#RequestMapping("/controller2")
Public Class Controller2{
#RequestMapping(method = RequestMethod.POST)
public void process(#RequestBody String jsonString) throws InterruptedException, ExecutionException
{
............
}
}
JSON request, request2, for the REST API(Controller2):
{
"key1":"value1",
"key2":"value2",
"key3":"value3"
}
I have several such "primitive" requests.
Now, I am expecting a JSON request, let's call it request3, which is a combination of such "primitive" queries- something that looks like below:
{
{
"requestType":"requestType1",
"request":"[{"key1":"value1","key2":"value2"}]"
},
{
"requestType":"requestType2",
"request":"[{"key1":"value1","key2":"value2","key3":"value3"}]"
}
}
Here, I need to trigger the respective API (one or two) upon identifying the query type. I wanna know how I can forward the request to the corresponding REST API. I wrote the REST API for request3 like below:
#RestController
#RequestMapping("/controller3")
Public Class Controller3{
#RequestMapping(method = RequestMethod.POST)
public void process(#RequestBody String jsonString) throws InterruptedException, ExecutionException
{
..................
..................
switch(request){
case request1: //how to call REST API 1?
case request2: //how to call REST API 2?
}
}
}
You can call a utility method which posts request to controller using Rest Template as below. Since you are using POST method it's easy to send parameters using Rest Template. You may need to edit this code a bit to work in your environment with exact syntax.
#RequestMapping( value= "/controller3" method = RequestMethod.POST)
public #ResponseBody void process(#RequestBody String jsonString){
String request = requestType //Get the request type from request
String url = "";
MultiValueMap<String, String> params= null;
switch(request){
case request1: //how to call REST API 1?
url = "/controller1";
params = request1param //Get the parameter map from request
case request2: //how to call REST API 2?
url = "/controller2";
params = request2Param //Get the parameter map from request
}
//Now call the method with parameters
getRESTResponse(url, params);
}
private String getRESTResponse(String url, MultiValueMap<String, String> params){
RestTemplate template = new RestTemplate();
HttpEntity<MultiValueMap<String, String>> requestEntity=
new HttpEntity<MultiValueMap<String, String>>(params);
String response = "";
try{
String responseEntity = template.exchange(url, HttpMethod.POST, requestEntity, String.class);
response = responseEntity.getBody();
}
catch(Exception e){
response = e.getMessage();
}
return response;
}
Redirect from one controller method to another controller method
Alternatively you also can call the rest method using Rest Template
Spring MVC - Calling a rest service from inside another rest service
You may find how to send POST request with params in this post
https://techie-mixture.blogspot.com/2016/07/spring-rest-template-sending-post.html
I am trying to make method Spring MVC method in controller to return text instead of json.
My current method looks like this
#RequestMapping(value = "/upload", method = RequestMethod.POST, produces = "text/html")
public ModelAndView uploadFile(#RequestParam("file") MultipartFile file) {
LOGGER.debug("Attempt to upload file with template.");
try {
String fileContent = FileProcessUtils.processFileUploading(file);
return createSuccessResponse(fileContent);
} catch (UtilityException e) {
LOGGER.error("Failed to process file.", e.getWrappedException());
return createResponse(INTERNAL_ERROR_CODE, e.getMessage());
}
}
But the response header content-type: application/json.
I was trying to pass HttpServletResponse to controller and set content type but it still continued to return json.
What's the problem?
What's FileProcessUtils? Google doesn't bring up anything. Is it a class created by you or your organization? It would appear that the method is returning a response with a content-type of application/json. What were you expecting it to return and why? You would have to somehow parse the json to extract the data necessary for constructing a ModelAndView or find another method that returns what you want.
But without more information on FileProcessUtils, it isn't possible to provide more of an answer.
You can either do this:
#RequestMapping(value = "/foo", method = RequestMethod.GET)
public ResponseEntity foo() throws Exception {
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.TEXT_HTML);
return ResponseEntity.ok().headers(headers).body("response");
}
or do this:
#RequestMapping(value = "/foo", method = RequestMethod.GET, produces = MediaType.TEXT_HTML_VALUE)
Both works fine.
I have to send JSON data from one service method to the other using postForObject() method.
I saw one example on RestTemplate on this link.
postForObject() method has the following format:
User returns = rt.postForObject(uri, u, User.class, vars);
Or
User returns = rt.postForObject(uri, u, User.class);
I want to know that, after using postForObject() method, if we implement the service method to accept the User object, how it will look like?
In my project, I have code like
RestTemplate restTemplate = new RestTemplate();
restTemplate.getMessageConverters().add(new MappingJacksonHttpMessageConverter());
restTemplate.getMessageConverters().add(new StringHttpMessageConverter());
String uri = "http://testcode.com/myapp/api/launchservices";
ServiceRequest request = new ServiceRequest();
request.setId(UUID.randomUUID().toString());
....
I am getting error at this line:
ServiceRequest req = restTemplate.postForObject(uri, request, ServiceRequest.class);
while executing this, I am getting this error mesage:
org.springframework.web.client.HttpClientErrorException: 400 Bad Request
at org.springframework.web.client.DefaultResponseErrorHandler.handleError(DefaultResponseErrorHandler.java:88)
at org.springframework.web.client.RestTemplate.handleResponseError(RestTemplate.java:537)
at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:493)
at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:452)
at org.springframework.web.client.RestTemplate.postForObject(RestTemplate.java:302)
my implementation method is:
#RequestMapping(value = "/launchservices", method = RequestMethod.POST)
#ResponseBody
public boolean launchServices(#PathVariable ServiceRequest request) {
System.out.println("Request: "+request.toString());
return true;
}
How to get rid of this? What will be the URI?
I got solution to this problem.
In this example,method postForObject returns an object of class "ServiceRequest"
ServiceRequest req = restTemplate.postForObject(uri, request, ServiceRequest.class);
So, the method that implements this service with the above 'uri' should return an object of class ServiceRequest
All it needs is, slight modification in implementation method as below
#RequestMapping(value = "/launchservices", method = RequestMethod.POST, headers = "Accept=application/json")
#ResponseBody
public ServiceRequest launchServices(#RequestBody ServiceRequest request) {
System.out.println("Request: "+request.toString());
return request;
}
final HttpResponse response = this.call(queryUri);
entity = response.getEntity();public HttpResponse call(final URI queryUri) throws Exception
{
Future<HttpResponse> futureResponses = executor.submit(new Callable<HttpResponse>()
{
#Override
public HttpResponse call() throws Exception
{
final HttpGet httpget = new HttpGet(queryUri);
return httpclient.execute(httpget);
}
});
return futureResponses.get(A9_CALL_TIMEOUT, TimeUnit.MILLISECONDS);
}
final HttpResponse response = this.call(queryUri);
entity = response.getEntity();
parse(entity.getcontent());
wondering how do I mock all the object, can someone provide me the workable code on test class?
I would recommend that you pull out the creation of the Callable to a protected method.
public Callable<HttpResponse> createCallable(String queryUri){
return new Callable<HttpResponse>(){
#Override
public HttpResponse call() throws Exception
{
final HttpGet httpget = new HttpGet(queryUri);
return httpclient.execute(httpget);
}
});
}
I don't think you actually need EasyMock for this test. In fact it might be easier without it. In your test you can override this method to return a test stub. I think if the get times out, then it will throw a TimeoutException and not actually cancel the job. So I think you just need to catch TimeoutException to make sure everything works.
So maybe your mock just has to sleep for A9_CALL_TIMEOUT plus some additional fudge factor.
#Test
public void testTimeout(){
Subclass sut = new Subclass(){
#Override
public Callable<HttpResponse> createCallable(String queryUri){
return new Callable<HttpResponse>(){
#Override
public HttpResponse call() throws Exception{
try{
Thread.sleep(A9_CALL_TIMEOUT *2);
catch(InterruptException e) {}
}
});
};
//you can also use Junit ExpectedException rule instead
// of the try catch here
try{
sut.runQueryMethodWithExecutor();
fail("should throw timeout");
}catch(TimeoutException e){
//expected
}
}