Compact mockito: shorter answer notation

[Update 2014.10.08] The code is now on github.

If you value brevity in tests like I do then maybe you would agree that mockito’s doAnswer statements contain much boilerplate. That is certainly not mockito’s fault but rather a result of java’s inflexible syntax. When testing, i.e. GWT code one will frequently find the need to mock RPC service interfaces:

Order someOrder = …

doAnswer(new Answer(){

public Object answer(InvocationOnMock invocation) throws Throwable {
AsyncCallback callback = (AsyncCallback)(invocation.getArguments()[2]);
return null;
}).when(orderService).getOrderForCustomer(eq(123), eq(456), any(AsyncCallback.class));

By using the BaseAnswer class discusses here you can achieve much shorter statements:

Order someOrder = ...

doAnswer(new BaseAnswer(){ @Override
public void getOrderForCustomer(int customerId, int orderId, AsyncCallback callback) {
}).when(orderService).getOrderForCustomer(eq(123), eq(456), any(AsyncCallback.class));

And this is the BaseAnswer class:
import java.lang.reflect.Method;

import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
import org.springframework.util.ReflectionUtils;

public abstract class BaseAnswer implements Answer{

private Class[] getClasses(Object[] arguments){
Class[] argClasses = new Class[arguments.length];
for (int i=0;i<arguments.length;i++){
if (arguments[i]!=null)
argClasses[i] = arguments[i].getClass();
return argClasses;

private double rateMatch(Class[] providedClasses, Class[] declaredClasses){
double score = -1;
if (providedClasses.length!=declaredClasses.length)
return -1;
for (int i=0;i<providedClasses.length;i++){
if (providedClasses[i] == null)
if (!declaredClasses[i].isAssignableFrom(providedClasses[i]))
return -1;
score = score/(double)providedClasses.length;
return score;

private Method findMethodWithArguments(Object[] arguments){
Class[] argClasses = getClasses(arguments);
Method[] methods = getClass().getDeclaredMethods();
Method bestMethod = null;
double bestMatch = -1;
for (Method method:methods){
double match = rateMatch(argClasses, method.getParameterTypes());
if (match>bestMatch){
bestMatch = match;
bestMethod = method;
return bestMethod;

private String argTypesToString(Object args[]){
Class[] classes = getClasses(args);
String s = "";
String prefix=",";
for (Class c:classes){
return s;

public T answer(InvocationOnMock invocation) throws Throwable {
Object[] arguments = invocation.getArguments();
Method method = findMethodWithArguments(arguments);
if (method == null)
throw new RuntimeException("This answer does not declare a method with these argument types: "+argTypesToString(arguments));
return (T)method.invoke(this, arguments);

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s