I have a stubbed JSON OBJECT but need to mock the following using Mockito:
HttpResponse response = defaultHttpClient.execute(postRequest);
BufferedReader rd = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));
StringBuilder result = new StringBuilder();
while ((line = rd.readLine()) != null) {
result.append(line);
}
JSONObject jsonResponseObject = new JSONObject(result.toString());
I have created the following Mocks:
@Mock
private HttpClient mockHttpClient;
private HttpPost mockHttpPost;
private HttpResponse mockHttpResponse;
private HttpEntity mockHttpEntity;
private InputStream mockInputStream;
private InputStreamReader mockInputStreamReader;
private BufferedReader mockBufferedReader;
And have the following when
statements:
Mockito.when(mockHttpClient.execute(mockHttpPost)).thenReturn(mockHttpResponse);
Mockito.when(mockHttpResponse.getEntity()).thenReturn(mockHttpEntity);
Mockito.when(mockHttpEntity.getContent()).thenReturn(mockInputStream);
Question: Do I need to create all these 'when' statements and if yes then which other ones do I need to create to be able to get to the stubbed JSON?
Any suggestions pls?
Thanks
In mockito you can mock all: interfaces, abstract classes, normal classes. In your case, if you want to simulate the behaviour of only execute() method you can mock the HttpClient interface.
The Mockito. mock() method allows us to create a mock object of a class or an interface. We can then use the mock to stub return values for its methods and verify if they were called.
Mockito mock method We can use Mockito class mock() method to create a mock object of a given class or interface. This is the simplest way to mock an object. We are using JUnit 5 to write test cases in conjunction with Mockito to mock objects.
We have two main options for mocking in our tests: Use Mockito to mimic the behavior of WebClient. Use WebClient for real, but mock the service it calls by using MockWebServer (okhttp)
You might have to mock HttpClient
and HttpResponse
, if they're interfaces (although, depending on your library, you could use MockHttpClient
or MockHttpResponse
), but you shouldn't be mocking anything else.
Why?
The mock is establishing expected output behavior on classes that we cannot make concrete, or rather, classes that we want to behave in a certain way for this particular instance of a test. You want to ensure that you get the correct response back from a mock HttpClient
, and that when response.getEntity()
is called, that it gives back a meaningful HttpEntity
. You can elect to mock that out or not; I personally wouldn't, as the mock doesn't add any extra value (except to perhaps verify that a particular method was called).
Everything else is a concrete implementation - you should be allowing the other objects to interact with the results of the previously mocked elements to ensure that they behave as they would if there were no mocks.
Actually...you really can't mock those unless you pass them in or inject them in some way. I would strongly discourage you from attempting to mock any new
ed objects in that method.
You don't specify what you're asserting, but I would expect that it's your JSONObject
in some capacity. I'd assert that what you expected to be placed into it actually made it into the JSON object, and also verify that your mocked objects were called and invoked in the way you expected them to be.
Your annotation @Mock
is not cascading, by the way - you have to annotate all mocked fields with @Mock
, then either annotate the test class with @RunWith(MockitoJunitRunner.class)
, or use MockitoAnnotation.initMocks(this)
(one or the other; both aren't required except under edge cases). If you choose the annotations, don't forget @InjectMocks
on your test object.
Lastly, your when
conditions do what I would expect them to do - those should be fine.
Yes, you might need all the when statements that you've mentioned.
But instead of returning the mockInputStream
, you could just return new ByteArrayInputStream( "{foo : 'bar'}".getBytes() )
Finally, you could verify that the json response object has a 'foo' property that has a value 'bar'.
That said, I'm not sure whether the given method is worth testing - since all it does it open streams and read data.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With