Reputation: 135
I am trying to mock a method which is opening a connection using URLConnection class and then getting stream input. I want to mock the URLConnection class efficiently but am not able to do so. Below is my code for:
Actual Method
@GetMapping(value = "/search/autocomplete")
public String autocomplete() {
try {
URL url = new URL("http://" + serverHost + ":" + serverPort + "/autocomplete");
URLConnection uc = url.openConnection();
String sb = toStringFromStream(uc.getInputStream());
return sb;
} catch (Exception e) {
log.warn(e.getMessage());
}
return "";
}
Test method:
@Test
public void autocomplete() throws Exception {
URL url = PowerMockito.mock(URL.class);
PowerMockito.whenNew(URL.class).withArguments("http://" + serverHost + ":" + serverPort +
"/autocomplete").thenReturn(url);
ReflectionTestUtils.setField(searchController,"serverHost","localhost");
ReflectionTestUtils.setField(searchController,"serverPort",3000);
InputStream anyInputStream = new ByteArrayInputStream("molly\nted".getBytes());
URLConnection uc = PowerMockito.mock(URLConnection.class);
PowerMockito.doReturn(uc).when(url).openConnection();
Mockito.doReturn(anyInputStream).when(uc).getInputStream();
PowerMockito.mock(Streamutils.class);
PowerMockito.when(Streamutils.toStringFromStream(anyInputStream)).thenReturn("molly");
String string = searchController.autocomplete();
assertEquals("",string);
}
When I run this test and call the actual method through it, URL url
takes up the http://localhost:3000/autocomplete
instead of the Mocked URL class. then uc
also doesnt take up the mocked value and opens connection even though I have provided mocking to it also here: URLConnection uc = PowerMockito.mock(URLConnection.class); PowerMockito.doReturn(uc).when(url).openConnection();
.Then String sb = toStringFromStream(uc.getInputStream());
this line executes from actual class and I donno why it always goes to exception block. Anyone suggest a fix for this issue please!
Upvotes: 1
Views: 1245
Reputation: 16209
Not the answer you requested, but some advice to avoid the problem.
I suggest not to make low level I/O operations part of the unit test. Split off the connection logic into a dependency and focus the unit test on your own business logic. If you write unit tests for low level stuff like this you are mostly testing framework code, not your own.
If you still want to confirm that the I/O works, write an integration test for that which actually connects to a URL.
EDIT: For a worthwile approach to integration testing see https://docs.pact.io/
Upvotes: 1