Explain Codes LogoExplain Codes Logo

Making a mocked method return an argument that was passed to it

java
mockito
testing
unit-testing
Alex KataevbyAlex KataevยทFeb 28, 2025
โšกTLDR

Mockito enables a mocked method to return its passed argument by utilizing the thenAnswer() method coupled with a lambda expression. This combination captures argument values using InvocationOnMock::getArguments and makes this possible. Behold the examples:

import static org.mockito.Mockito.*; MyClass myClass = mock(MyClass.class); // Shh... Not a parrot but echoes the first argument. ๐Ÿ˜„ when(myClass.myMethod(anyString())).thenAnswer(invocation -> (String) invocation.getArguments()[0]);

This brief code sets the myMethod to return its first string argument. The joy here? No extra Answer interface implementation. Only simple and short lambdas.

Dynamic stubbing made easy with thenAnswer()

thenAnswer() method provides dynamic stubbing capabilities in Mockito. It helps you extend mocking needs beyond simple returns. Find here an advanced simulation of a dynamic echo:

when(myClass.myMethod(anyString())).thenAnswer(invocation -> { String arg = (String) invocation.getArguments()[0]; // Some string manipulations just because we can. return "Modified: " + arg; });

How to handle various argument types with Mockito

Your method could accept multiple argument types, and Mockito offers a solution for all:

when(myClass.myMethod(anyInt())).thenAnswer(invocation -> invocation.getArguments()[0]); when(myClass.myMethod(any(MyComplexClass.class))) .thenAnswer(invocation -> invocation.getArguments()[0]);

Simple mocking with returnsFirstArg()

When you need only the first argument, Mockito lets you cut the chase with returnsFirstArg():

import static org.mockito.AdditionalAnswers.returnsFirstArg; // The first argument is always special, isn't it? ๐Ÿ˜„ when(myClass.myMethod(anyString())).then(returnsFirstArg());

Void methods? No worries. Use doAnswer()

For void methods, use doAnswer():

doAnswer(invocation -> { String arg = (String) invocation.getArguments()[0]; // Echoing in the console just for some fun. System.out.println("Argument received: " + arg); return null; // Void means void. So, we return null. }).when(myClass).myVoidMethod(anyString());

Confirm mock behavior with assertions

We use assertions to verify if our mock behaves as expected. Here's how:

String testString = "test"; assertEquals(testString, myClass.myMethod(testString));

And for void methods with side effects, validate their changes like so:

myClass.myVoidMethod("effect"); verify(myClass).myVoidMethod("effect"); // Operation successful, if there is an "effect".

Customizing mock's behavior with Answer

Answer interface in Mockito allows you to create complex behaviors. Here's an example:

when(myClass.someMethod(any())).thenAnswer(new Answer<String>() { public String answer(InvocationOnMock invocation) { Object[] args = invocation.getArguments(); // Add custom logic using args return processedResult; } });

Perfecting argument matching with Mockito

Flexibility is crucial in testing different scenarios. Argument matchers in Mockito offer exactly this. Here's how to do it:

when(myClass.myMethod(nullable(String.class))).then(returnsFirstArg()); when(myClass.myMethod(isA(MyType.class))).then(returnsFirstArg());

Testing data persistence with mocks

Mocking in Mockito goes a long way to simulate data retrieval scenarios. Consider the following map that mimics a database:

Map<String, String> mockDatabase = new HashMap<>(); when(mockRepository.getData(anyString())) .thenAnswer(invocation -> mockDatabase.get(invocation.getArguments()[0]));

Just add data to mockDatabase during testing for data presence and absence.