I am currently writing unit test for below method
#Autowired
private RequestConfig requestConfig;
#Autowired
private RetryTemplate retryTemplate;
public ResponseEntity<String> makeGetServiceCall(String serviceUrl) throws Exception {
try {
return retryTemplate.execute(retryContext -> {
RestTemplate restTemplate = new RestTemplate();
HttpHeaders headers = requestConfig.createHttpHeaders();
HttpEntity<String> entity = new HttpEntity<String>("parameters", headers);
ResponseEntity<String> response = restTemplate.exchange(serviceUrl, HttpMethod.GET, entity, String.class);
return response;
});
} catch (Exception e) {
throw new Exception("Generic exception while makeGetServiceCall due to" + e + serviceUrl);
}
}
UPDATED METHOD:
#Autowired
private RequestConfig requestConfig;
#Autowired
private RetryTemplate retryTemplate;
#Autowired
private RestTemplate restTemplate;
public ResponseEntity<String> makeGetServiceCall(String serviceUrl) throws Exception {
try {
return retryTemplate.execute(retryContext -> {
HttpHeaders headers = requestConfig.createHttpHeaders();
HttpEntity<String> entity = new HttpEntity<String>("parameters", headers);
ResponseEntity<String> response = restTemplate.exchange(serviceUrl, HttpMethod.GET, entity, String.class);
return response;
});
} catch (Exception e) {
throw new Exception("Generic exception while makeGetServiceCall due to" + e + serviceUrl);
}
}
I tried all possibilities but I am unable to get it right. Here is my below test.
#Mock
private RestTemplate restTemplate;
#Mock
public RequestConfig requestConfig;
#InjectMocks
private RetryTemplate retryTemplate;
ServiceRequest serviceRequest;
#Test
public void makeGetServiceCall() throws Exception {
String url = "http://localhost:8080";
RetryTemplate mockRetryTemplate = Mockito.mock(RetryTemplate.class);
RestTemplate mockRestTemplate = Mockito.mock(RestTemplate.class);
ResponseEntity<String> myEntity = new ResponseEntity<>(HttpStatus.ACCEPTED);
Mockito.when(mockRetryTemplate.execute(ArgumentMatchers.any(RetryCallback.class), ArgumentMatchers.any(RecoveryCallback.class), ArgumentMatchers.any(RetryState.class))).thenReturn(myEntity);
Mockito.when(mockRestTemplate.exchange(
ArgumentMatchers.eq(url),
ArgumentMatchers.eq(HttpMethod.GET),
ArgumentMatchers.<HttpEntity<String>>any(),
ArgumentMatchers.<Class<String>>any())
).thenReturn(myEntity);
ResponseEntity<String> response = serviceRequest.makeGetServiceCall(url);
Assert.assertEquals(myEntity, response);
}
UPDATED TEST CASE:
#Mock
public RequestConfig requestConfig;
#Mock
private RestTemplate restTemplate;
#Mock
private RetryTemplate retryTemplate;
#InjectMocks
ServiceRequest serviceRequest;
#Test
public void makeGetServiceCall() throws Exception {
//given:
String url = "http://localhost:8080";
when(requestConfig.createHttpHeaders()).thenReturn(null);
ResponseEntity<String> myEntity = new ResponseEntity<>( HttpStatus.ACCEPTED);
when(retryTemplate.execute(any(RetryCallback.class), any(RecoveryCallback.class), any(RetryState.class))).thenAnswer(invocation -> {
RetryCallback retry = invocation.getArgument(0);
return retry.doWithRetry(/*here goes RetryContext but it's ignored in ServiceRequest*/null);
});
when(restTemplate.exchange(anyString(), any(HttpMethod.class), any(HttpEntity.class), eq(String.class)))
.thenReturn(myEntity);
//when:
ResponseEntity<String> response = serviceRequest.makeGetServiceCall(url);
//then:
assertEquals(myEntity, response);
}
The response object which I get from my method call makeGetServiceCall always return null. When I debug the code I see exception org.mockito.exceptions.misusing.WrongTypeOfReturnValue: ResponseEntity cannot be returned by toString() toString() should return String error on the resttemplate mocking where I return myEntity
I am not sure what am I missing.
Well, you have made quite some number of mistakes...
I'm sure you wanted to annotate private RetryTemplate retryTemplate; with #Mock, not #InjectMocks
#InjectMocks should go onto ServiceRequest serviceRequest;
You are defining interactions on some mockRetryTemplate and mockRestTemplate which have nothing to do with serviceRequest. Instead, you should use your #Mock-annotated fields to define interactions on because they are being injected into your object under test (serviceRequest)
Moreover, you can't normally mock RestTemplate and inject it into your ServiceRequest because you don't use dependency injection in the first place for RestTemplate in ServiceRequest. You just instantiate its instance in ServiceRequest.makeGetServiceCall
You are defining an interaction on the wrong method at line Mockito.when(retryTemplate.execute(.... Your interaction specifies RetryTemplate.execute(RetryCallback, RecoveryCallback, RetryState) whereas your ServiceRequest uses another method RetryTemplate.execute(RetryCallback)
You should also notice that RetryTemplate.execute is final and so you can't mock it without extra efforts as explained here. And generally, you should prefer interfaces over classes, e.g. RestOperations and RetryOperations over RestTemplate and RetryTemplate respectively, to be more flexible.
That said, below is the working test which solves your problem. But take note of removing RestTemplate restTemplate = new RestTemplate(); from ServiceRequest and making restTemplate a field so it's dependency-injected.
#RunWith(MockitoJUnitRunner.class)
public class ServiceRequestTest {
#Mock
private RestTemplate restTemplate;
#Mock
public RequestConfig requestConfig;
#Mock
private RetryTemplate retryTemplate;
#InjectMocks
ServiceRequest serviceRequest;
#Test
public void makeGetServiceCall() throws Exception {
//given:
String url = "http://localhost:8080";
ResponseEntity<String> myEntity = new ResponseEntity<>(HttpStatus.ACCEPTED);
when(retryTemplate.execute(any(RetryCallback.class))).thenAnswer(invocation -> {
RetryCallback retry = invocation.getArgument(0);
return retry.doWithRetry(/*here goes RetryContext but it's ignored in ServiceRequest*/null);
});
when(restTemplate.exchange(eq(url), eq(HttpMethod.GET), any(HttpEntity.class), eq(String.class)))
.thenReturn(myEntity);
//when:
ResponseEntity<String> response = serviceRequest.makeGetServiceCall(url);
//then:
assertEquals(myEntity, response);
}
}
For me below worked, otherwise, it was returning null always
when(retryTemplate.execute(any(),any(),any())).thenAnswer(invocation -> {
RetryCallback retry = invocation.getArgument(0);
return retry.doWithRetry(null);
});
and import was
import static org.mockito.ArgumentMatchers.any;
Generic solution:
Mockito.when(retryTemplate.execute(Matchers.any(),Matchers.any(),Matchers.any())).thenAnswer(invocation -> {
RetryCallback retry = invocation.getArgumentAt(0,Matchers.any());
return retry.doWithRetry(null);
});
It works for me!
#ExtendWith(MockitoExtension.class)
class RetryableRestClientTest {
#Mock
private RestTemplate restTemplate;
#Mock
private RetryTemplate retryTemplate;
#InjectMocks
private RetryableRestClient client;
#SuppressWarnings("rawtypes")
#Test
void test_get() {
String url = "https://faked-url";
ResponseEntity<String> expectedResponseEntity = new ResponseEntity<>(HttpStatus.OK);
Mockito.when(retryTemplate.execute(Mockito.any(), Mockito.any(), Mockito.any()))
.thenAnswer(invocation -> {
RetryCallback retry = invocation.getArgument(0);
return retry.doWithRetry(null);
});
Mockito.when(restTemplate.exchange(Mockito.eq(url), Mockito.eq(HttpMethod.GET), Mockito.any(HttpEntity.class), Mockito.eq(String.class)))
.thenReturn(expectedResponseEntity);
ResponseEntity<String> actualResponseEntity = client.get(url);
Assertions.assertEquals(expectedResponseEntity, actualResponseEntity);
}
}
#Component
public class RetryableRestClient {
#Autowired
private RetryTemplate retryTemplate;
#Autowired
private RestTemplate restTemplate;
private HttpHeaders fakeHttpHeaders() {
HttpHeaders headers = new HttpHeaders();
// fake browser's behavior
headers.add("authority", "m.nowscore.com");
headers.add("cache-control", "max-age=0");
headers.add("sec-ch-ua", "\" Not;A Brand\";v=\"99\", \"Google Chrome\";v=\"91\", \"Chromium\";v=\"91\"");
headers.add("sec-ch-ua-mobile", "?0");
headers.add("upgrade-insecure-requests", "1");
headers.add("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.114 Safari/537.36");
headers.add("accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9");
headers.add("sec-fetch-site", "none");
headers.add("sec-fetch-mode", "navigate");
headers.add("sec-fetch-user", "?1");
headers.add("sec-fetch-dest", "document");
headers.add("accept-language", "en-US,en;q=0.9");
return headers;
}
public final ResponseEntity<String> get(String url) {
return retryTemplate.execute(context -> restTemplate.exchange(url, HttpMethod.GET, new HttpEntity<>(null, fakeHttpHeaders()), String.class));
}
}
Related
I am working on a non-spring application and using restTemplate feature from spring-web.While writing Junit test i am unable to mock response from restTemplate.postForEntity(). What am i doing wrong here.
Below is the function
public JsonObject apiResponse(Request request) throws JsonProcessingException {
String queryRequest = objectMapper.writeValueAsString(request);
HttpHeaders headers = new HttpHeaders();
headers.add("content-type", "application/json");
RestTemplate restTemplate = new RestTemplate();
ResponseEntity<String> responseEntity = restTemplate.postForEntity(
"https://testurl/test/",
new HttpEntity<>(queryRequest, headers), String.class);
return JsonParser.parseString(Objects.requireNonNull(responseEntity.getBody())).getAsJsonObject();
Below is the Junit
#ExtendWith(MockitoExtension.class)
public class HandlerTest {
#Spy
#InjectMocks
Handler handler;
#Mock
RestTemplate restTemplate;
#Test
public void apiREsponseTest() throws JsonProcessingException {
//this is not working
Mockito.doReturn(new ResponseEntity <>("test", HttpStatus.OK))
.when(restTemplate).postForEntity(eq("test"), eq(HttpEntity.class), eq(String.class));
assertNotNull(handler.apiResponse(request));
RestTemplate restTemplate = new RestTemplate();
This is not getting mocked as it's a local object and it will always call the real method. You can try this to mock the restTemplate:
RestTemplate restTemplate = getRestTemplate();
protected RestTemplate getRestTemplate() {
return new RestTemplate();
}
//Add this stub to your test
when(handler.getRestTemplate()).thenReturn(restTemplate);
The URL is hardcoded here:
ResponseEntity<String> responseEntity = restTemplate.postForEntity(
"https://testurl/test/",
new HttpEntity<>(queryRequest, headers), String.class);
Hence the you need to change your stubbing as well.
Mockito.doReturn(new ResponseEntity <>("test", HttpStatus.OK))
.when(restTemplate).postForEntity(eq("https://testurl/test/"), eq(HttpEntity.class), eq(String.class));
Making these changes should make your test green hopefully. Let me know if this doesn't resolve your issue.
first of all I try to write unit-test for remote service to get weather and using restTemplate then implement ClientHttpRequestInterceptor to get remote request && remote response for logging purpose now i try to mock restTemplate to write unit-test and get the following error
When using matchers, all arguments have to be provided by matchers.
For example:
//correct:
someMethod(anyObject(), eq("String by matcher"));
For more info see javadoc for Matchers class.
and here you here code i wrote for unit-test
#RunWith(MockitoJUnitRunner.class)
public class WeatherRemoteServiceTest {
#Mock CustomResttemplate restTemplate;
#Mock WeatherRemoteUtilies weatherUtilies;
#InjectMocks WeatherRemoteService weatherRemote;
#Test
public void testRetrieveWeather() {
ResponseEntity<String> MockResponse= new ResponseEntity<String>(HttpStatus.OK);
Mockito.when(weatherUtilies.buildRequestParams(Mockito.anyString()))
.thenReturn(Mockito.any(MultiValueMap.class));
ResponseEntity<String> responseEntity = new ResponseEntity<String>("sampleBodyString", HttpStatus.OK);
Mockito.when(restTemplate.buildRestTemplate().exchange(
Matchers.anyString(),
Matchers.any(HttpMethod.class),
Matchers.<HttpEntity<?>> any(),
Matchers.<Class<String>> any()
)
).thenReturn(responseEntity);
assertEquals(weatherRemote.retrieveWeather("ciaro").getStatusCode(), HttpStatus.OK);
}
}
and here is code for business logic itself
#Service
public class WeatherRemoteService {
private final Logger logger= LoggerFactory.getLogger(this.getClass());
#Value("${openweather.url}")
private String url;
#Autowired
private WeatherRemoteUtilies weatherUtilies;
#Autowired
private CustomResttemplate customRestTemplate;
public ResponseEntity<?> retrieveWeather(String city) {
logger.info(Constants.CLASS_NAME+this.getClass().getName()+Constants.METHOD_NAME+new Object() {}.getClass().getEnclosingMethod().getName());
logger.debug(Constants.METHOD_ARGUMENTS+city);
RestTemplate restRequest= customRestTemplate.buildRestTemplate();
HttpHeaders headers= new HttpHeaders();
headers.set("Accept",MediaType.APPLICATION_JSON_UTF8_VALUE);
UriComponentsBuilder uri= UriComponentsBuilder.fromUriString(url).
path("/data/2.5/weather")
.queryParams(weatherUtilies.buildRequestParams(city));
HttpEntity<String>entity= new HttpEntity<>(headers);
ResponseEntity<String>WeatherResponse=restRequest.exchange(uri.toUriString(), HttpMethod.GET, entity, String.class);
logger.info(Constants.END_METHOD);
return WeatherResponse;
}
}
code for RestTemplateInterceptor
public class RestTemplateInterceptor implements ClientHttpRequestInterceptor {
private final Logger logger =LoggerFactory.getLogger(this.getClass());
#Override
public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution)
throws IOException {
logRequest(request, body);
ClientHttpResponse httpResponse= execution.execute(request, body);
logResponse(httpResponse);
return httpResponse;
}
private void logRequest(HttpRequest request, byte[] body) throws IOException {
logger.info(Constants.START_REMOTE_REQUEST);
logger.info("URI :{}", request.getURI().toString());
logger.info("Method :{}", request.getMethod().toString());
logger.info("Headers :{}", request.getHeaders().toString());
logger.info("Request body :{}", new String(body,"UTF-8").toString());
logger.info(Constants.END_REMOTE_REQUEST);
}
private void logResponse(ClientHttpResponse response) throws IOException {
logger.info(Constants.START_REMOTE_RESPONSE);
logger.info("Status code :{}", response.getStatusCode().toString());
logger.info("Status text :{}", response.getStatusText().toString());
logger.info("Headers :{}", response.getHeaders().toString());
logger.info("Response body :{}", StreamUtils.copyToString(response.getBody(), Charset.defaultCharset()));
logger.info(Constants.END_REMOTE_RESPONSE);
}
}
then setInterceptor on RestTemplate factory using the following code
public class CustomResttemplate {
public RestTemplate buildRestTemplate() {
SimpleClientHttpRequestFactory simpleFactory= new SimpleClientHttpRequestFactory();
simpleFactory.setOutputStreaming(false);
ClientHttpRequestFactory factory = new BufferingClientHttpRequestFactory(simpleFactory);
RestTemplate restTemplate= new RestTemplate(factory);
restTemplate.setInterceptors(Collections.singletonList(new RestTemplateInterceptor()));
return restTemplate;
}
}
Your problem is where you write
.thenReturn(Mockito.any(MultiValueMap.class))
You actually have to tell Mockito what to return. You can't use a matcher here. Matchers are for verifying, and for setting up what conditions to stub. You can't use them to tell Mockito what to return from a stubbed call.
Create a specific MultiValueMap to pass to thenReturn.
Can anyone show me an example, how to test RestTemplate using Spock.
My classes looks like this:
#Service
public class SomeService {
#Autowired
private EndpointUrlProvider endpointUrlProvider;
private RestTemplate restTemplate = new RestTemplate();
public SomeResponse doSomePostRequest(HttpEntity<?> httpEntity) throws Exception {
ResponseEntity<SomeResponse> response;
try{
response = restTemplate.postForEntity(endpointUrlProvider.getSomeUrl(),httpEntity,SomeResponse.class);
} catch (Exception e){
throw new Exception("Exception occured during post for:" + httpEntity.getBody().getClass().getSimpleName() + " Cause: " + e.getMessage());
}
if(response.getStatusCode() == HttpStatus.OK){
return response.getBody();
}
throw new Exception("Error during " + response.getBody().getClass().getSimpleName() + "Http status is diffrent than 200: " + response.getBody().toString());
}
}
Tests:
class SomeTest extends Specification {
RestTemplate restTemplate = Mock {
postForEntity(_, _, SomeResponse.class) >> new ResponseEntity(new SomeResponse(), HttpStatus.OK)
}
#Autowired
SomeService someService
def "someTest"() {
when:
SomeResponse someResponse = someService.doSomePostRequest(new HttpEntity<>(new SomeBody(), new HttpHeaders()))
then:
someResponse == new SomeResponse()
}
}
The major problem is mocking behaviour of RestTemplate,I looking for solution how to do it in proper way. I'm dont use spring boot.
The situation is following:
You create new RestTemplate in your service class.
private RestTemplate restTemplate = new RestTemplate();
Then you create mock in tests and call your service method:
RestTemplate restTemplate = Mock {
postForEntity(_, _, SomeResponse.class) >> new ResponseEntity(new SomeResponse(), HttpStatus.OK)
}
....
someService.doSomePostRequest
But your service still has usual rest template inside. You should inject mock object. I would suggest you doing it through constructor. So change your code to:
#Service
public class SomeService {
private EndpointUrlProvider endpointUrlProvider;
private RestTemplate restTemplate;
#Autowired
public SomeService(EndpointUrlProvider endpointUrlProvider, RestTemplate restTemplate){
this.endpointUrlProvider = endpointUrlProvider;
this.restTemplate = restTemplate;
}
And your test will be:
class SomeTest extends Specification {
RestTemplate restTemplate = Mock {
postForEntity(_, _, SomeResponse.class) >> new ResponseEntity(new SomeResponse(), HttpStatus.OK)
}
SomeService someService = new SomeService ( null, restTemplate);
def "someTest"() {
when:
SomeResponse someResponse = someService.doSomePostRequest(new HttpEntity<>(new SomeBody(), new HttpHeaders()))
then:
someResponse == new SomeResponse()
}
}
Now your service object will call method on injected MOCK, not usual RestTemplate
p.s.
Constructor injection considered to be a good practice by spring.
It's better to create a RestTemplate bean and inject it everywhere, than create new object in all services.
I have a demo filter to log request/response body and verify the request signature, if signature is wrong the filter would be redirect to my error controller. And I have some test case to check this filter:
post the correct signature by using RestTemplate
post the wrong signature by using RestTemplate
post the correct signature by using MockMvc
post the wrong signature by using MockMvc
when I run that, case 1,2,3 were correct. but the case 4 has some problem.
I found that case 4 has run this code, but it did not redirect to my error controller.
RequestDispatcher requestDispatcher = getServletContext().getRequestDispatcher("/error/signError");
requestDispatcher.forward(requestWrapper, responseWrapper);
Whether I used the default MockMvc by #Autowired or used the MockMvcBuilders to create, this code did not work.
So, I confuse how much different about the MockMvc and RestTemplate, and is RequestDispatcher possible to work by using MockMvc?
The filter code:
#Component
public class ApiFilter extends OncePerRequestFilter {
private static final Logger LOG = LoggerFactory.getLogger(ApiFilter.class);
#Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
String requestId = UUID.randomUUID().toString();
String requestBody = IOUtils.toString(request.getInputStream(), StandardCharsets.UTF_8);
LOG.info("request id [{}] requset body [{}]", requestId, requestBody);
ApiRequestWrapper requestWrapper = null;
ApiResponseWrapper responseWrapper = null;
try {
requestWrapper = new ApiRequestWrapper(requestId, request, requestBody);
responseWrapper = new ApiResponseWrapper(requestId, response);
System.out.println(request.getRequestURI());
System.out.println(request.getRequestURL());
System.out.println(request.getPathInfo());
System.out.println(getServletContext());
if (StringUtils.equalsIgnoreCase(request.getHeader(ApiConstant.HEAD_SIGN), DigestUtils.md5Hex(requestBody + ApiConstant.API_TOKEN))) {
filterChain.doFilter(requestWrapper, responseWrapper);
} else {
// redirect to error response
RequestDispatcher requestDispatcher = getServletContext().getRequestDispatcher("/error/signError");
requestDispatcher.forward(requestWrapper, responseWrapper);
}
} finally {
LOG.info("request id [{}] response body [{}]", requestId, responseWrapper);
}
}
}
and my test case like this.
#RunWith(SpringRunner.class)
#SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
#AutoConfigureMockMvc
public class LoginContorllerTest {
#Autowired ObjectMapper objectMapper;
//#Autowired
MockMvc mockMvc;
#Autowired TestRestTemplate restTemplate;
#Autowired WebApplicationContext webApplicationContext;
#Autowired ApiFilter apiFilter;
#Before
public void init() throws Exception {
MockFilterConfig filterConfig = new MockFilterConfig(webApplicationContext.getServletContext(), "apiFilter");
apiFilter.init(filterConfig);
this.mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).addFilter(apiFilter, "/api/*").build();
}
#Test
public void mockTest() throws Exception {
System.out.println("mockTest");
LoginParam param = new LoginParam();
param.setUsername("test");
param.setPassword("123456");
String requestBody = objectMapper.writeValueAsString(param);
String sign = DigestUtils.md5Hex(requestBody + ApiConstant.API_TOKEN);
String contentAsString = mockMvc
.perform(post("/api/login").header(ApiConstant.HEAD_SIGN, sign).contentType(MediaType.APPLICATION_JSON_UTF8).content(requestBody))
.andExpect(status().isOk())
.andReturn()
.getResponse()
.getContentAsString();
// please forgive me using this way in the demo
System.out.println(contentAsString);
System.out.println();
}
#Test
public void mockSignErrorTest() throws Exception {
System.out.println("mockSignErrorTest");
LoginParam param = new LoginParam();
param.setUsername("test");
param.setPassword("123456");
String requestBody = objectMapper.writeValueAsString(param);
String contentAsString = mockMvc
.perform(post("/api/login").header(ApiConstant.HEAD_SIGN, "12254548858").contentType(MediaType.APPLICATION_JSON_UTF8).content(requestBody))
.andReturn()
.getResponse()
.getContentAsString();
System.out.println(contentAsString);
System.out.println();
}
#Test
public void restTest() throws Exception {
System.out.println("restTest");
LoginParam param = new LoginParam();
param.setUsername("test");
param.setPassword("123456");
String requestBody = objectMapper.writeValueAsString(param);
String sign = DigestUtils.md5Hex(requestBody + ApiConstant.API_TOKEN);
HttpHeaders headers = new HttpHeaders();
headers.add(ApiConstant.HEAD_SIGN, sign);
HttpEntity<LoginParam> httpEntity = new HttpEntity<LoginParam>(param, headers);
ResponseEntity<String> result = this.restTemplate.exchange("/api/login", HttpMethod.POST, httpEntity, String.class);
System.out.println(result.getBody());
System.out.println();
}
#Test
public void restSignErrorTest() throws Exception {
System.out.println("restSignErrorTest");
LoginParam param = new LoginParam();
param.setUsername("test");
param.setPassword("123456");
HttpHeaders headers = new HttpHeaders();
headers.add(ApiConstant.HEAD_SIGN, "123456789");
HttpEntity<LoginParam> httpEntity = new HttpEntity<LoginParam>(param, headers);
ResponseEntity<String> result = this.restTemplate.exchange("/api/login", HttpMethod.POST, httpEntity, String.class);
System.out.println(result.getBody());
System.out.println();
}
}
I want to mock the resttemplate call which is instansiated as local variable and exchange method invoked. I mocked using expectation but it invokes the actual method . Am I missing something . Please help me on this . Thanks in advance
public class ServiceController {
public String callGetMethod (HttpServletRequest request){
String url = request.getParameter("URL_TO_CALL");
HttpHeaders headers = new HttpHeaders();
headers.setAccept(Arrays.asList(MediaType.APPLICATION_JSON));
HttpEntity<String> entity = new HttpEntity<String>(headers);
RestTemplate restTemplate = new RestTemplate();
ResponseEntity<String> res = restTemplate.exchange(url, HttpMethod.GET, entity, String.class);
return res.getBody();
}
}
#RunWith(JMockit.class)
public class ServiceControllerTest {
#Tested
private ServiceController controller;
#Test
public void callGetMethod (#Mocked HttpServletRequest request, #Mocked RestTemplate restTemplate){
new NonStrictExpectations() {
{
restTemplate.exchange(host,HttpMethod.GET, entity,String.class); returns (new ResponseEntity<String>("success" , HttpStatus.OK));
}
ResponseEntity<String> response = controller.callGetMethod(httpServletRequest);
}
}
We need to mock the new RestTemplate() . So that it will assign mocked object restTemplate to method local variable .
#Mocked
RestTemplate restTemplate;
new NonStrictExpectations() {
{
new RestTemplate();
result = restTemplate;
restTemplate.exchange(host, HttpMethod.GET, entity, String.class);
returns(new ResponseEntity<String>("success", HttpStatus.OK));
}