CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/maven-org-mockito--mockito-core

Mockito mock objects library core API and implementation for comprehensive Java unit testing

Pending
Overview
Eval results
Files

additional-answers.mddocs/

Additional Answer Behaviors

This section covers advanced stubbing behaviors that go beyond basic return values and exception throwing, providing sophisticated answer strategies for complex testing scenarios.

Argument-Based Return Values

Return First Argument

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 Second Argument

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 varargs

Return Last Argument

Return 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 type

Return Argument at Position

Return 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)

Call Delegation

Delegate to Real Object

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 realRepo

Collection-Based Returns

Return Elements from Collection

Return 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));

Delayed Answers

Answer with Delay

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;  // ~1000ms

Functional Interface Answers

Typed Return Answers (1-6 Parameters)

Create 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));

Typed Void Answers (1-6 Parameters)

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());

Complex Answer Combinations

Combining Multiple Answer Strategies

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());

Import Statements

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 needed

This provides access to all additional answer methods including returnsFirstArg, returnsSecondArg, returnsLastArg, returnsArgAt, delegatesTo, returnsElementsOf, answersWithDelay, and the type-safe answer/answerVoid methods.

Best Practices

When to Use Additional Answers

  • Argument Echoing: Use returnsFirstArg, returnsSecondArg, returnsLastArg, returnsArgAt when the return value should be one of the input parameters
  • Partial Mocking: Use delegatesTo for final classes, proxied objects, or when you need most real behavior with selective stubbing
  • Sequential Data: Use returnsElementsOf when simulating iterative processes or data streams
  • Performance Testing: Use answersWithDelay to simulate network latency, database delays, or slow operations
  • Type Safety: Use answer/answerVoid with functional interfaces for compile-time type checking and cleaner lambda expressions

Performance Considerations

  • delegatesTo calls real methods, which may have performance implications or side effects
  • answersWithDelay introduces actual delays in test execution - use judiciously
  • Functional interface answers have minimal overhead compared to traditional Answer implementations

Testing Guidelines

// 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); // Better

Debugging Tips

When 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

docs

additional-answers.md

additional-matchers.md

advanced-features.md

annotations.md

argument-matching.md

bdd-testing.md

index.md

mock-creation.md

static-mocking.md

stubbing.md

verification.md

tile.json