0

In my test class I am mocking HTTPclient but when I run test class it calls actual method instead of mock at line

 final HttpResponse response = httpClient.execute(postRequest);

and gives me java.lang.IllegalStateException.

Here is my code

  final HttpClient httpClient = new DefaultHttpClient();
  final HttpPost postRequest = new HttpPost(someURL);
  final String inputJson = mapper.writeValueAsString(someObj);
  final StringEntity input = new StringEntity(inputJson);

  input.setContentType("application/json");
  postRequest.setEntity(input);
  final HttpResponse response = httpClient.execute(postRequest);

  if (response.getStatusLine().getStatusCode() != 200) {
               throw new RuntimeException("Failed : HTTP error code : " + response.getStatusLine().getStatusCode());
  }

  final BufferedReader br = new BufferedReader(new InputStreamReader((response.getEntity().getContent())));

and here is my Test class code

public class XGenericServiceTest {


@InjectMocks
private XGenericService xGenericService = new XGenericService();

@Mock
HttpClient httpClient;

@Mock
HttpResponse httpResponse;

@Mock
HttpEntity httpEntity;

@Mock
StatusLine statusLine;

@Mock
HttpPost httpPost;

@Before
public void init() {
    MockitoAnnotations.initMocks(this);

}

  @Test
  public void testgetXClient(){

    try {
            String s =  "[{\"firstName\":\"adasd\"}]";
when(httpClient.execute(Mockito.isA(HttpPost.class))).thenReturn(httpResponse);
            when(httpResponse.getStatusLine()).thenReturn(statusLine);
            when(statusLine.getStatusCode()).thenReturn(HttpStatus.SC_OK);
            when(httpEntity.getContent()).thenReturn(new ByteArrayInputStream(s.getBytes()));
            when(httpResponse.getEntity()).thenReturn(httpEntity);
            List<MdmClient> results = xGenericService.getXClient("userId", "surname", "givenName", "postalCode", "availableId", "phoneNumber", "organizationName", "otherKey");

    } catch (Exception e) {
        e.printStackTrace();
    } 

  }

}

but I am getting following exception

java.lang.IllegalStateException: Target host must not be null, or set in parameters.
at org.apache.http.impl.client.DefaultRequestDirector.determineRoute(DefaultRequestDirector.java:784)
at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:414)
at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:906)
at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:805)
at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:784)
at au.com.allianz.omnia.service.SafireGenericService.getSafireClient(SafireGenericService.java:87)
at au.com.allianz.omnia.service.SafireGenericServiceTest.testgetSafireClient(SafireGenericServiceTest.java:61)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:88)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:55)
at java.lang.reflect.Method.invoke(Method.java:613)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:47)

Can anybody point me what is wrong with above code?

user327126
  • 965
  • 3
  • 11
  • 22

1 Answers1

1

From the code snippet shared it is evident that HttpClient and HttpPost are instantiated via new operator instead of using any instance level injected (i.e. autowired) objects.

 final HttpClient httpClient = new DefaultHttpClient();
 final HttpPost postRequest = new HttpPost(someURL);

Thus the @InjectMocks and @Mock essentially have no effect and the real instance of HttpClient and HttpPost are used when invoked from test class; which explains the error encountered.

In this particular scenario Mockito (perhaps any mocking framework) can't help. To proceed, if possible, refactor the code under test such as to use the instance level injected object(s) instead of using the instance created via new operator.

Bond - Java Bond
  • 3,972
  • 6
  • 36
  • 59
  • `new` is inside the class which is going to be tested, not in the test class. – Vikash Yadav Jul 26 '19 at 10:10
  • Do read the question and this answer _again_ to understand the behavior. – Bond - Java Bond Jul 26 '19 at 10:13
  • "To proceed, if possible, refactor the code under test such as to use the instance level injected object(s) instead of using the instance created via new operator." here you asked to refactor in test but **in test** no new operator is used. – Vikash Yadav Jul 26 '19 at 10:40
  • Incorrect interpretation. I have asked to refactor _code under test_ (which means the service class code and not the test code). – Bond - Java Bond Jul 26 '19 at 10:49
  • Ok, but it's not working in my case- https://stackoverflow.com/questions/57218251/mocking-execte-method-of-httpclient/57219131#57219131 – Vikash Yadav Jul 26 '19 at 11:36
  • I have voted the (other) question as duplicate. As mentioned here, the service code need to be refactored so that the mocking can be utilized. – Bond - Java Bond Jul 26 '19 at 11:49
  • what need to be to refactored? and question mentioned in link is not duplicate, there are many differences if you look closely – Vikash Yadav Jul 26 '19 at 12:21