Skip to content
Advertisement

Mocking a Nested Object in Junit

I have a service I am mocking like this:

@ExtendWith(MockitoExtension.class)
class MyServiceTest {

@InjectMocks
MyService myService;



    @Test
    void testSendRec() {
       myService.sendDocRec(.. pass params..);
    }

}

the service:

@Service
public class MyService {

    String sendDocRec( params ) {

       // builds request
       HttpUriRequestBase request = getRequest(  params );

        String response = doRequest(request);
    }

    public String doRequest(ClassicHttpRequest request) {
    String result = null;

        try (CloseableHttpClient httpclient = HttpClients.custom()
                .setConnectionManager(this.connectionManager)
                .setConnectionManagerShared(true) 
                .setDefaultRequestConfig(this.requestConfig)
                .build()) {

            final HttpClientContext clientContext = HttpClientContext.create();

            try (CloseableHttpResponse response = httpclient.execute(request, clientContext)) {

                result = EntityUtils.toString(response.getEntity());
            
            }
        } catch (URISyntaxException e) {
            log.error("Invalid URI {}", e);
        } catch (IOException e) {
            log.error("Failed to make HTTP Request {}", e);
        } catch (ParseException e) {
            log.error("Failed parsing response body {}", e);
        }

        return result;
    }

}

I need to be able to mock the “CloseableHttpResponse response = httpclient.execute(request, clientContext)”, such that the “response” object is something I create ahead of time. I am hoping some mocking when/then constructs would work for this? I would grateful for ideas on how to do this. Thanks!

Advertisement

Answer

You can’t do it using the current code structure. httpclient object is getting created within the method under test. So it can’t be mocked.

You need to delegate httpclient object creation to another method with belongs to a different class (something similar to HttpClientFactory class). That HttpClientFactory class should only be responsible for creating httpClient instances. If you need you can write separate unit test case for the class.

 @Inject
 private HttpClientFactory httpClientFactory;

      public String doRequest(ClassicHttpRequest request) {
        String result = null;
    
            try (CloseableHttpClient httpclient = httpClientFactory.getInstance()) {
    
                final HttpClientContext clientContext = HttpClientContext.create();
    
                try (CloseableHttpResponse response = httpclient.execute(request, clientContext)) {
    
                    result = EntityUtils.toString(response.getEntity());
                
                }
            } catch (URISyntaxException e) {
                log.error("Invalid URI {}", e);
            } catch (IOException e) {
                log.error("Failed to make HTTP Request {}", e);
            } catch (ParseException e) {
                log.error("Failed parsing response body {}", e);
            }
    
            return result;
        }

Now you can mock response like below:

 @Mock
 private HttpClientFactory httpClientFactory;

public String testDoRequest(ClassicHttpRequest request) {
....
    CloseableHttpClient mockedClient = mock(CloseableHttpClient.class);
    CloseableHttpResponse mockedResponse = mock(CloseableHttpResponse.class);
    when(httpClientFactory.getInstance()).thenReturn(mockedClient);
    when(mockedClient.execute(eq(request), any(clientContext))).thenReturn(mockedResponse);
....}

User contributions licensed under: CC BY-SA
5 People found this is helpful
Advertisement