Dendin
Dendin

Reputation: 173

Mocking a method inside a non-mocked method

I'm trying to mock a method that is being called inside another method that is being unit tested. However, the mock is not working properly and I am getting an UnknownHostException that I would get if i never mocked the inside method in the first place. It might be my throws declarations as I am unaware how else to do it. Any help is appreciated.

My test is this so far:

@Test
public void testServiceValidHost() throws ClientProtocolException, IOException {
    HealthService service = new HealthService();
    HealthService spy = Mockito.spy(service);

    when(spy.getHTTPResponse("http://" + HOST + "/health")).thenReturn(SOMESTATUS);

    String actual = spy. executeHealthCheck(HOST);
    assertEquals(SOMESTATUS, actual);
}

The method I am testing is executeHealthCheck, and i want to mock getHTTPResponse

public String executeHealthCheck(String host) {
    try {
        String responseBody = getHTTPResponse("http://" + host + "/health");
        return responseBody;
    } catch (UnknownHostException e) {
        ...
        return "Invalid Host";
    } catch (Exception e) {
        ...
        return "Error";
    }
}

public String getHTTPResponse(String url) throws IOException, ClientProtocolException {
    CloseableHttpResponse response = null;
    HttpGet httpGet = new HttpGet(url);
    response = client.execute(httpGet);
    JSONObject responseBody = new JSONObject(EntityUtils.toString(response.getEntity()));
    return responseBody.toString();
}

Upvotes: 8

Views: 7155

Answers (1)

Nkosi
Nkosi

Reputation: 247551

Consider mocking the class and arranging for the method under test to be actually called while stubbing the desired members.

For example

@Test
public void testServiceValidHost() throws ClientProtocolException, IOException {
    //Arrange    
    HealthService service = Mockito.mock(HealthService.class);

    when(service.executeHealthCheck(HOST)).callRealMethod();
    when(service.getHTTPResponse("http://" + HOST + "/health")).thenReturn(SOMESTATUS);

    //Act
    String actual = service.executeHealthCheck(HOST);

    //Assert
    assertEquals(SOMESTATUS, actual);
}

However according to the docs, one of the Important gotcha on spying real objects!

Sometimes it's impossible or impractical to use when(Object) for stubbing spies. Therefore when using spies please consider doReturn|Answer|Throw() family of methods for stubbing.

@Test
public void testServiceValidHost() throws ClientProtocolException, IOException {
    //Arrange
    HealthService service = new HealthService();
    HealthService spy = Mockito.spy(service);

    //You have to use doReturn() for stubbing
    doReturn(SOMESTATUS).when(spy).getHTTPResponse("http://" + HOST + "/health");

    //Act
    String actual = spy.executeHealthCheck(HOST);

    //Assert
    assertEquals(SOMESTATUS, actual);
}

Upvotes: 6

Related Questions