Gregory Javis
Gregory Javis

Reputation: 135

How to Mock URLConnection class using Mockito

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

Answers (1)

Adriaan Koster
Adriaan Koster

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

Related Questions