Mockito mock objects library core API and implementation for comprehensive Java unit testing
—
This section covers advanced stubbing behaviors that go beyond basic return values and exception throwing, providing sophisticated answer strategies for complex testing scenarios.
Return the first parameter of an invocation as the method's return value.
public static <T> Answer<T> returnsFirstArg()Usage Examples:
CarKeyFob mockKeyFob = mock(CarKeyFob.class);
PersonService mockPerson = mock(PersonService.class);
// Return the first argument passed to the method
when(mockKeyFob.authenticate(any(CarKey.class))).will(returnsFirstArg());
when(mockPerson.remember(any(Dream.class), any(Dream[].class))).will(returnsFirstArg());
// Use the mock
CarKey key = new CarKey("ABC123");
CarKey result = mockKeyFob.authenticate(key); // Returns the same CarKey instance
Dream dream1 = new Dream("flying");
Dream result2 = mockPerson.remember(dream1, new Dream("falling")); // Returns dream1
// Works with varargs - returns first individual argument
Dream[] dreams = {new Dream("running"), new Dream("swimming")};
Dream result3 = mockPerson.remember(dreams[0], dreams[1]); // Returns dreams[0]Return the second parameter of an invocation as the method's return value.
public static <T> Answer<T> returnsSecondArg()Usage Examples:
TraderService mockTrader = mock(TraderService.class);
PersonService mockPerson = mock(PersonService.class);
// Return the second argument passed to the method
when(mockTrader.apply(any(Formula.class), any(Swap.class))).will(returnsSecondArg());
when(mockPerson.remember(any(Dream.class), any(Dream[].class))).will(returnsSecondArg());
// Use the mock
Formula formula = new Formula("Lee's Formula");
Swap swap = new CreditDefaultSwap();
Swap result = mockTrader.apply(formula, swap); // Returns the swap instance
Dream dream1 = new Dream("flying");
Dream dream2 = new Dream("falling");
Dream[] otherDreams = mockPerson.remember(dream1, dream2, new Dream("running"));
// Returns otherDreams array when second parameter is varargsReturn the last parameter of an invocation as the method's return value.
public static <T> Answer<T> returnsLastArg()Usage Examples:
PersonService mockPerson = mock(PersonService.class);
// Return the last argument passed to the method
when(mockPerson.remember(any(Dream.class), any(), any(), any())).will(returnsLastArg());
// Use the mock
Dream dream1 = new Dream("flying");
Dream dream2 = new Dream("falling");
Dream dream3 = new Dream("running");
Dream dream4 = new Dream("swimming");
Dream result = mockPerson.remember(dream1, dream2, dream3, dream4); // Returns dream4
// Works with varargs - returns last element or varargs array
Dream[] varargDreams = {new Dream("dancing")};
Dream[] result2 = mockPerson.rememberArray(dream1, dream2, dream3, varargDreams);
// Returns varargDreams array if return type matches varargs typeReturn the parameter at a specific position in the invocation.
public static <T> Answer<T> returnsArgAt(int position)Usage Examples:
PersonService mockPerson = mock(PersonService.class);
// Return argument at index 2 (zero-based)
when(mockPerson.remember(any(), any(), any(), any())).will(returnsArgAt(2));
// Use the mock
Dream dream1 = new Dream("flying");
Dream dream2 = new Dream("falling");
Dream dream3 = new Dream("running");
Dream dream4 = new Dream("swimming");
Dream result = mockPerson.remember(dream1, dream2, dream3, dream4); // Returns dream3
// Works with varargs expansion
when(mockPerson.remember(any(Dream.class), any(Dream[].class))).will(returnsArgAt(2));
Dream expandedResult = mockPerson.remember(dream1, dream2, dream3, dream4);
// Returns dream3 (varargs expanded to individual arguments)Forward all method calls to a delegate object, useful for partial mocks and final classes.
public static <T> Answer<T> delegatesTo(Object delegate)Usage Examples:
// Final class that can't be spied normally
final class DontYouDareToMockMe implements List<String> {
private List<String> list = new ArrayList<>();
@Override
public boolean add(String item) {
return list.add(item);
}
@Override
public String get(int index) {
return list.get(index);
}
// ... other List methods
}
DontYouDareToMockMe awesomeList = new DontYouDareToMockMe();
awesomeList.add("delegated-item");
// Create mock that delegates to the real object
List<String> mockList = mock(List.class, delegatesTo(awesomeList));
// Method calls are forwarded to awesomeList
String result = mockList.get(0); // Returns "delegated-item"
// Important: Use doReturn for stubbing to avoid calling real method
doReturn("stubbed-value").when(mockList).get(0);
// Delegate can be different type with compatible method signatures
UserRepository realRepo = new DatabaseUserRepository();
UserRepository mockRepo = mock(UserRepository.class, delegatesTo(realRepo));
// Calls will be forwarded to realRepoReturn elements from a collection sequentially, repeating the last element forever.
public static <T> Answer<T> returnsElementsOf(Collection<?> elements)Usage Examples:
NumberService mockService = mock(NumberService.class);
// Return elements in sequence
List<Integer> numbers = Arrays.asList(1, 2, 3);
when(mockService.getNextNumber()).thenAnswer(returnsElementsOf(numbers));
// Use the mock
int first = mockService.getNextNumber(); // Returns 1
int second = mockService.getNextNumber(); // Returns 2
int third = mockService.getNextNumber(); // Returns 3
int fourth = mockService.getNextNumber(); // Returns 3 (last element repeats)
int fifth = mockService.getNextNumber(); // Returns 3 (continues repeating)
// Equivalent to traditional stubbing
// when(mockService.getNextNumber()).thenReturn(1, 2, 3);
// Works with any collection type
Set<String> statuses = new LinkedHashSet<>(Arrays.asList("pending", "processing", "completed"));
when(mockService.getStatus()).thenAnswer(returnsElementsOf(statuses));Return an answer after a specified delay in milliseconds.
public static <T> Answer<T> answersWithDelay(long sleepyTime, Answer<T> answer)Usage Examples:
NetworkService mockService = mock(NetworkService.class);
// Simulate network latency
Answer<String> delayedResponse = answersWithDelay(1000, invocation -> "response");
when(mockService.fetchData()).thenAnswer(delayedResponse);
// Use with other answers
Answer<String> delayedArgReturn = answersWithDelay(500, returnsFirstArg());
when(mockService.echo(anyString())).thenAnswer(delayedArgReturn);
// Combine with exception throwing
Answer<String> delayedFailure = answersWithDelay(200,
invocation -> { throw new TimeoutException("Simulated timeout"); });
when(mockService.unreliableCall()).thenAnswer(delayedFailure);
// Use the mock
long start = System.currentTimeMillis();
String result = mockService.fetchData(); // Takes ~1000ms to return
long elapsed = System.currentTimeMillis() - start; // ~1000msCreate strongly-typed answers using functional interfaces for methods that return values.
public static <T, A> Answer<T> answer(Answer1<T, A> answer)
public static <T, A, B> Answer<T> answer(Answer2<T, A, B> answer)
public static <T, A, B, C> Answer<T> answer(Answer3<T, A, B, C> answer)
public static <T, A, B, C, D> Answer<T> answer(Answer4<T, A, B, C, D> answer)
public static <T, A, B, C, D, E> Answer<T> answer(Answer5<T, A, B, C, D, E> answer)
public static <T, A, B, C, D, E, F> Answer<T> answer(Answer6<T, A, B, C, D, E, F> answer)Usage Examples:
UserService mockService = mock(UserService.class);
// Single parameter answer with type safety
Answer1<User, String> userByName = name -> new User(name.toLowerCase());
when(mockService.findUser(anyString())).thenAnswer(answer(userByName));
// Two parameter answer
Answer2<String, String, Integer> formatter = (name, age) -> name + " (" + age + ")";
when(mockService.formatUser(anyString(), anyInt())).thenAnswer(answer(formatter));
// Three parameter answer with complex logic
Answer3<Double, Double, Double, String> calculator = (x, y, operation) -> {
switch (operation) {
case "add": return x + y;
case "multiply": return x * y;
default: return 0.0;
}
};
when(mockService.calculate(anyDouble(), anyDouble(), anyString()))
.thenAnswer(answer(calculator));
// Using method references
Answer1<String, String> upperCaser = String::toUpperCase;
when(mockService.transform(anyString())).thenAnswer(answer(upperCaser));
// Lambda expressions for simple cases
when(mockService.processNumber(anyInt()))
.thenAnswer(answer((Integer n) -> n * 2));Create strongly-typed answers using functional interfaces for void methods.
public static <A> Answer<Void> answerVoid(VoidAnswer1<A> answer)
public static <A, B> Answer<Void> answerVoid(VoidAnswer2<A, B> answer)
public static <A, B, C> Answer<Void> answerVoid(VoidAnswer3<A, B, C> answer)
public static <A, B, C, D> Answer<Void> answerVoid(VoidAnswer4<A, B, C, D> answer)
public static <A, B, C, D, E> Answer<Void> answerVoid(VoidAnswer5<A, B, C, D, E> answer)
public static <A, B, C, D, E, F> Answer<Void> answerVoid(VoidAnswer6<A, B, C, D, E, F> answer)Usage Examples:
LoggingService mockService = mock(LoggingService.class);
// Single parameter void answer
VoidAnswer1<String> logger = message -> System.out.println("LOG: " + message);
doAnswer(answerVoid(logger)).when(mockService).log(anyString());
// Two parameter void answer
VoidAnswer2<String, LogLevel> levelLogger = (message, level) ->
System.out.println("[" + level + "] " + message);
doAnswer(answerVoid(levelLogger)).when(mockService).log(anyString(), any(LogLevel.class));
// Complex void behavior with side effects
List<String> auditLog = new ArrayList<>();
VoidAnswer3<String, String, Date> auditor = (user, action, timestamp) -> {
auditLog.add(user + " performed " + action + " at " + timestamp);
};
doAnswer(answerVoid(auditor)).when(mockService).audit(anyString(), anyString(), any(Date.class));
// Method reference for existing methods
VoidAnswer1<String> printer = System.out::println;
doAnswer(answerVoid(printer)).when(mockService).output(anyString());
// Lambda for state modification
AtomicInteger counter = new AtomicInteger(0);
doAnswer(answerVoid((String msg) -> counter.incrementAndGet()))
.when(mockService).log(anyString());Create sophisticated mock behaviors by combining different answer types.
Usage Examples:
PaymentService mockService = mock(PaymentService.class);
// Combine delegation with delay for realistic simulation
PaymentProcessor realProcessor = new DefaultPaymentProcessor();
Answer<PaymentResult> realisticAnswer = answersWithDelay(500, delegatesTo(realProcessor));
when(mockService.processPayment(any())).thenAnswer(realisticAnswer);
// Sequential behavior with different answer types
when(mockService.getTransactionId())
.thenAnswer(returnsElementsOf(Arrays.asList("TX001", "TX002", "TX003")))
.thenAnswer(answer((InvocationOnMock inv) -> "TX" + System.currentTimeMillis()));
// Argument-dependent answers with functional interfaces
Answer2<String, String, Double> feeCalculator = (type, currency) -> {
if ("premium".equals(type)) return 0.01;
if ("USD".equals(currency)) return 0.025;
return 0.03;
};
when(mockService.calculateFee(anyString(), anyString()))
.thenAnswer(answer(feeCalculator));
// Error simulation with delays
Answer<Void> unreliableService = answersWithDelay(1000,
answerVoid((String request) -> {
if (request.contains("error")) {
throw new ServiceException("Simulated failure");
}
}));
doAnswer(unreliableService).when(mockService).processRequest(anyString());To use AdditionalAnswers, include these imports in your test files:
import static org.mockito.AdditionalAnswers.*;
import org.mockito.stubbing.Answer1;
import org.mockito.stubbing.Answer2;
import org.mockito.stubbing.VoidAnswer1;
import org.mockito.stubbing.VoidAnswer2;
// Import additional Answer3-Answer6 and VoidAnswer3-VoidAnswer6 as neededThis provides access to all additional answer methods including returnsFirstArg, returnsSecondArg, returnsLastArg, returnsArgAt, delegatesTo, returnsElementsOf, answersWithDelay, and the type-safe answer/answerVoid methods.
returnsFirstArg, returnsSecondArg, returnsLastArg, returnsArgAt when the return value should be one of the input parametersdelegatesTo for final classes, proxied objects, or when you need most real behavior with selective stubbingreturnsElementsOf when simulating iterative processes or data streamsanswersWithDelay to simulate network latency, database delays, or slow operationsanswer/answerVoid with functional interfaces for compile-time type checking and cleaner lambda expressionsdelegatesTo calls real methods, which may have performance implications or side effectsanswersWithDelay introduces actual delays in test execution - use judiciously// Good: Clear intent with appropriate answer type
when(mockCache.get(anyString())).will(returnsFirstArg()); // Cache returns what you put in
// Good: Type-safe functional answers
Answer1<User, Long> userLoader = id -> userRepository.findById(id);
when(mockService.loadUser(anyLong())).thenAnswer(answer(userLoader));
// Good: Realistic simulation
when(mockNetworkService.fetchData())
.thenAnswer(answersWithDelay(100, returnsElementsOf(testData)));
// Avoid: Using delegation when simple stubbing suffices
// when(mockList.size()).thenAnswer(delegatesTo(realList)); // Overkill
when(mockList.size()).thenReturn(5); // BetterWhen using complex answers, consider logging or debugging support:
// Add logging to functional answers for debugging
Answer1<String, String> debuggingProcessor = input -> {
String result = processInput(input);
System.out.println("Processed '" + input + "' -> '" + result + "'");
return result;
};
when(mockService.process(anyString())).thenAnswer(answer(debuggingProcessor));Install with Tessl CLI
npx tessl i tessl/maven-org-mockito--mockito-core