A comprehensive Java mocking framework that enables developers to create test doubles for unit testing.
—
Stubbing allows you to define the behavior of mock methods. When a stubbed method is called, it returns the predefined value or performs the specified action instead of the default behavior.
The standard way to stub methods:
public static <T> OngoingStubbing<T> when(T methodCall);
public interface OngoingStubbing<T> {
OngoingStubbing<T> thenReturn(T value);
OngoingStubbing<T> thenReturn(T value, T... values);
OngoingStubbing<T> thenThrow(Throwable... throwables);
OngoingStubbing<T> thenThrow(Class<? extends Throwable> throwableType);
OngoingStubbing<T> thenAnswer(Answer<?> answer);
OngoingStubbing<T> thenCallRealMethod();
T getMock();
}Usage Examples:
List<String> mock = mock(List.class);
// Return values
when(mock.get(0)).thenReturn("first");
when(mock.get(1)).thenReturn("second");
// Multiple return values in sequence
when(mock.size()).thenReturn(1, 2, 3);
// Throw exceptions
when(mock.get(anyInt())).thenThrow(new RuntimeException("Error"));
when(mock.clear()).thenThrow(UnsupportedOperationException.class);Stub methods to return different values on consecutive calls:
when(mock.someMethod("some arg"))
.thenReturn("one", "two", "three");
// First call returns "one", second returns "two", third and subsequent return "three"Alternative stubbing syntax, especially useful for void methods and spies:
public static Stubber doReturn(Object toBeReturned);
public static Stubber doThrow(Throwable toBeThrown);
public static Stubber doThrow(Class<? extends Throwable> toBeThrown);
public static Stubber doAnswer(Answer answer);
public static Stubber doNothing();
public static Stubber doCallRealMethod();
public interface Stubber {
<T> T when(T mock);
Stubber doReturn(Object toBeReturned);
Stubber doThrow(Throwable... toBeThrown);
Stubber doAnswer(Answer answer);
Stubber doNothing();
Stubber doCallRealMethod();
}Usage Examples:
List<String> mock = mock(List.class);
// Return values
doReturn("element").when(mock).get(0);
// Throw exceptions
doThrow(new RuntimeException()).when(mock).clear();
// Do nothing (for void methods)
doNothing().when(mock).clear();
// Call real method
doCallRealMethod().when(mock).size();
// Chaining multiple behaviors
doReturn("first")
.doReturn("second")
.doThrow(new RuntimeException())
.when(mock).get(anyInt());@Deprecated
public static <T> VoidMethodStubbable<T> stubVoid(T mock);Modern approach using do-family:
// Void method that should throw exception
doThrow(new RuntimeException()).when(mock).clear();
// Void method that should do nothing (default behavior)
doNothing().when(mock).clear();
// Void method that should call real method (for spies)
doCallRealMethod().when(spy).clear();Create complex stubbing behavior with custom logic:
public interface Answer<T> {
T answer(InvocationOnMock invocation) throws Throwable;
}
public interface InvocationOnMock {
Object getMock();
Method getMethod();
Object[] getArguments();
<T> T getArgument(int index);
<T> T callRealMethod() throws Throwable;
}Usage Examples:
// Custom answer with argument access
when(mock.get(anyInt())).thenAnswer(new Answer<String>() {
public String answer(InvocationOnMock invocation) {
Object[] args = invocation.getArguments();
return "Element at index " + args[0];
}
});
// Lambda-based answer (Java 8+)
when(mock.get(anyInt())).thenAnswer(invocation -> {
int index = invocation.getArgument(0);
return "Element " + index;
});
// Answer that calls real method
when(spy.someMethod()).thenAnswer(invocation -> {
// Custom logic before
Object result = invocation.callRealMethod();
// Custom logic after
return result;
});Mockito provides several predefined answers:
public class AdditionalAnswers {
public static <T> Answer<T> returnsFirstArg();
public static <T> Answer<T> returnsSecondArg();
public static <T> Answer<T> returnsLastArg();
public static <T> Answer<T> returnsArgAt(int position);
public static <T> Answer<T> delegatesTo(Object delegate);
}Usage Examples:
// Return first argument
when(mock.process(anyString())).then(returnsFirstArg());
// Return argument at specific position
when(mock.transform(anyString(), anyInt())).then(returnsArgAt(1));
// Delegate to real object
UserService realService = new UserService();
when(mock.process(anyString())).then(delegatesTo(realService));Use argument matchers to create flexible stubs:
// Exact matching
when(mock.get("key")).thenReturn("value");
// Argument matchers
when(mock.get(anyString())).thenReturn("default");
when(mock.process(eq("input"))).thenReturn("output");
when(mock.calculate(anyInt(), gt(10))).thenReturn(100);
// Custom matchers
when(mock.validate(argThat(s -> s.length() > 5))).thenReturn(true);// Good - specific stubbing
when(userService.findById(123)).thenReturn(user);
// Avoid - overly broad stubbing
when(userService.findById(anyInt())).thenReturn(user);// Good - match expected return type
when(mock.getUsers()).thenReturn(Arrays.asList(user1, user2));
// Avoid - mismatched types
when(mock.getUsers()).thenReturn(null); // Better to return empty list// Good - handle null inputs
when(service.process(null)).thenThrow(IllegalArgumentException.class);
when(service.process(anyString())).thenReturn("processed");
// Good - handle different scenarios
when(service.save(any(User.class)))
.thenReturn(true) // First call succeeds
.thenReturn(false); // Second call failsList<String> spy = spy(new ArrayList<>());
// WRONG - can cause issues with spies
when(spy.get(0)).thenReturn("stubbed");
// CORRECT - use do-family for spies
doReturn("stubbed").when(spy).get(0);// WRONG - incomplete stubbing
when(mock.someMethod()); // Missing thenReturn/thenThrow
// CORRECT
when(mock.someMethod()).thenReturn("value");// WRONG - return type mismatch
when(mock.size()).thenReturn("not a number");
// CORRECT
when(mock.size()).thenReturn(42);// WRONG - can't use when() with void methods
when(mock.clear()).thenReturn(something); // Compilation error
// CORRECT
doNothing().when(mock).clear();
doThrow(new RuntimeException()).when(mock).clear();Install with Tessl CLI
npx tessl i tessl/maven-org-mockito--mockito-all