Grab an argument in Mockito

I am testing a specific class. This class internally creates a GetMethod object, which is passed to the "HttpClient" object, which is injected into the test class.

I am mocking the "HttpClient" class, but I will need to change the behavior of one method of the "GetMethod" class. I play with an ArgumentCaptor, but I seem to be unable to hold an instance of the object in the when call.

Example:

HttpClient mockHttpClient = mock(HttpClient.class); ArgumentCaptor<GetMethod> getMethod = ArgumentCaptor.forClass(GetMethod.class); when(mockHttpClient.executeMethod(getMethod.capture())).thenReturn(HttpStatus.SC_OK); when(getMethod.getValue().getResponseBodyAsStream()).thenReturn(new FileInputStream(source)); 

Answer:

 org.mockito.exceptions.base.MockitoException: No argument value was captured! You might have forgotten to use argument.capture() in verify()... ...or you used capture() in stubbing but stubbed method was not called. Be aware that it is recommended to use capture() only with verify() 
+6
java unit-testing testing mockito
source share
2 answers

Well, that’s how I decided it. A bit confusing, but did not find another way.

In the test class:

 private GetMethod getMethod; public void testMethod() { when(mockHttpClient.executeMethod(any(GetMethod.class))).thenAnswer(new ExecuteMethodAnswer()); //Execute your tested method here. //Acces the getMethod here, assert stuff against it. } private void setResponseStream(HttpMethodBase httpMethod, InputStream inputStream) throws NoSuchFieldException, IllegalAccessException { Field privateResponseStream = HttpMethodBase.class.getDeclaredField("responseStream"); privateResponseStream.setAccessible(true); privateResponseStream.set(httpMethod, inputStream); } private class ExecuteMethodAnswer implements Answer { public Object answer(InvocationOnMock invocation) throws FileNotFoundException, NoSuchFieldException, IllegalAccessException { getMethod = (GetMethod) invocation.getArguments()[0]; setResponseStream(getMethod, new FileInputStream(source)); return HttpStatus.SC_OK; } } 
+4
source share

You cannot use when in getMethod because getMethod is not a layout. This is still the real object created by your class.

ArgumentCaptor has a completely different purpose. Mark section 15 here .

You can make your code more verifiable. As a rule, classes that create new instances of other classes are difficult to verify. Put some factory in this class to create get / post methods, then in the mock this factory test and make it a false get / post method.

 public class YourClass { MethodFactory mf; public YourClass(MethodFactory mf) { this.mf = mf; } public void handleHttpClient(HttpClient httpClient) { httpClient.executeMethod(mf.createMethod()); //your code here } } 

Then in the test you can do:

 HttpClient mockHttpClient = mock(HttpClient.class); when(mockHttpClient.executeMethod(any(GetMethod.class)).thenReturn(HttpStatus.SC_OK); MethodFactory factory = mock(MethodFactory.class); GetMethod get = mock(GetMethod.class); when(factory.createMethod()).thenReturn(get); when(get.getResponseBodyAsStream()).thenReturn(new FileInputStream(source)); 

UPDATE

You can also try a few nasty hacks and Answer and access the private parts of GetMethod;) by reflection. (This is a really nasty hack)

 when(mockHttpClient.executeMethod(any(GetMethod.class))).thenAnswer(new Answer() { Object answer(InvocationOnMock invocation) { GetMethod getMethod = (GetMethod) invocation.getArguments()[0]; Field respStream = HttpMethodBase.class.getDeclaredField("responseStream"); respStream.setAccessible(true); respStream.set(getMethod, new FileInputStream(source)); return HttpStatus.SC_OK; } }); 
+12
source share

All Articles