Why does my Mockito mock object use real the implementation
I had an issue with mocking Apache Http client. The following attempt to create a mock:
DefaultHttpClient httpClient = Mockito.mock(DefaultHttpClient.class);
Fails to create a true mock. The above row gets executed without exceptions, but when I try to stub some behavior:
Mockito.when(httpClient.execute(Mockito.<HttpUriRequest>anyObject())).thenReturn(null);
I get an exception from a method in AbstractHttpClient:
Exception in thread "main" java.lang.IllegalArgumentException: Request must not be null.
at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:572)
at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java开发者_StackOverflow中文版:554)
Why is the call to execute inside Mockito.when passed to AbstractHttpClient?
I found a solution to this specific problem: use the interface HttpClient instead of trying to mock the concrete subclass. This is a far better solution in this case, but I am wondering in general what's going on here? Why can't I mock this concrete class properly with Mockito? Is there something special about DefaultHttpClient? Are there other cases where Mockito can't mock concrete classes?
I'm using Mockito 1.8.5, Apache httpclient 4.0.3, Apache http core 4.1, JDK 1.6.0 on OSX
Several of the methods on AbstractHttpClient are final and thus won't be mocked. IMO, this behavior is the #1 reason not to mock concrete classes.
Try this syntax (just a sample, not a real code):
import static Mockito.*;
// ...
HttpClient httpClient = mock(HttpClient.class);
doReturn(null).when(httpClient).execute(anyObject()).
See this link for better explanation of the problem/solution: http://docs.mockito.googlecode.com/hg/org/mockito/Mockito.html#doReturn(java.lang.Object)
精彩评论