Team,
My Service will run as Stand Alone program,
My Code:
public class TestRestTemplate {
private RestTemplate restTemplate;
public TestRestTemplate() {
restTemplate = new RestTemplate();
}
public void identifyInvoiceCategory(final Properties properties) throws Throwable {
final ResponseEntity<SearchResponse> exchange = restTemplate.exchange(
properties.getProperty("ENDPOINT"), HttpMethod.GET,
new HttpEntity<>(createSearchRequest(), createHttpHeader()), SearchResponse.class);
final SearchResponse searchResponse = exchange.getBody();
searchResponse.getEndIndex();
}
private SearchRequest createSearchRequest() throws Throwable {
final SearchRequest searchRequest = new SearchRequest();
return searchRequest;
}
private HttpHeaders createHttpHeader() {
HttpHeaders httpHeaders = new HttpHeaders();
httpHeaders.setContentType(MediaType.APPLICATION_JSON);
return httpHeaders;
}
}
My Junit test Code
@RunWith(MockitoJUnitRunner.class)
public class TestRest {
@Mock
private RestTemplate restTemplate;
@Test
public void testIdentifyInvoiceCategoryValid() throws Throwable {
try {
Mockito.when(restTemplate.exchange(ArgumentMatchers.anyString(), ArgumentMatchers.eq(HttpMethod.GET),
ArgumentMatchers.any(), ArgumentMatchers.<Class<SearchResponse>>any())).thenReturn(null);
new TestRestTemplate().identifyInvoiceCategory(createProperties());
} catch (Throwable genThrowable) {
genThrowable.printStackTrace();
}
}
private Properties createProperties() {
final Properties properties = new Properties();
properties.setProperty("ENDPOINT", "http://www.test.com");
return properties;
}
}
When I run the JUNIT, I am getting the following exception
org.springframework.web.client.ResourceAccessException: I/O error on GET request for "http://www.test.com": Connection timed out: connect; nested exception is java.net.ConnectException: Connection timed out: connect
at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:791)
at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:717)
at org.springframework.web.client.RestTemplate.exchange(RestTemplate.java:608)
at com.gxs.orch.aggregator.util.TestRestTemplate.identifyInvoiceCategory(TestRestTemplate.java:23)
It looks like, it is trying to connect to the actual URL instead of Mocking...
Could you please help me to resolve this?
You mocked RestTemplate
, but nowhere in your test you're actually injecting it into TestRestTemplate
. Because of that, TestTestTemplate
is using the RestTemplate
you're creating in your constructor.
The first step is to inject your mock in TestRestTemplate
. The easiest way to do this is by using the @InjectMocks
annotation:
@RunWith(MockitoJUnitRunner.class)
public class TestRest {
// Add this field:
@InjectMocks
private TestRestTemplate testRestTemplate;
@Mock
private RestTemplate restTemplate;
// ...
}
After that, you have to refactor your tests so that they use the TestRestTemplate
instance created by Mockito rather than using your own. This means that everywhere you use new TestRestTemplate()
, you now refer to the testRestTemplate
field.
For example:
@Test
public void testIdentifyInvoiceCategoryValid() throws Throwable {
// ...
// Don't use new TestRestTemplate():
testRestTemplate.identifyInvoiceCategory(createProperties());
// ...
}
Also, while it's not really necessary for @InjectMocks
to work, it's considered a bad practice to create a new RestTemplate
instance within the constructor of TestRestTemplate
because it increases coupling. To solve this, you can refactor your constructor to accept an external RestTemplate
instance:
public class TestRestTemplate {
private RestTemplate restTemplate;
// Refactor your constructor to this:
public TestRestTemplate(RestTemplate restTemplate) {
this.restTemplate = restTemplate;
}
// ...
}
Some other recommendations:
@ExtendWith(MockitoExtension.class)
rather than using @RunWith()
.RestTemplate
has several overloaded methods that achieve the same thing: to call a REST API. Ideally you shouldn't rely in your tests on the right overloaded method being called. In stead of that, you should verify whether the right API call was made, regardless of what RestTemplate
method you use. For that purpose, you can use MockRestServiceServer
.