Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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();
}
like image 893
Dendin Avatar asked Aug 10 '18 01:08

Dendin


People also ask

Is it possible to call the actual methods after mocking a class?

Mockito allows us to partially mock an object. This means that we can create a mock object and still be able to call a real method on it. To call a real method on a mocked object we use Mockito's thenCallRealMethod().

How do you mock a method in the same class?

Mocking is done when you invoke methods of a class that has external communication like database calls or rest calls. Through mocking you can explicitly define the return value of methods without actually executing the steps of the method.

How do you mock a method?

Mockito when() method It should be used when we want to mock to return specific values when particular methods are called. In simple terms, "When the XYZ() method is called, then return ABC." It is mostly used when there is some condition to execute. Following code snippet shows how to use when() method: when(mock.

What is the difference between spy and mock in Mockito?

Mocks are used to create fully mock or dummy objects. It is mainly used in large test suites. Spies are used for creating partial or half mock objects. Like mock, spies are also used in large test suites.


1 Answers

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);
}
like image 103
Nkosi Avatar answered Oct 06 '22 04:10

Nkosi