Explain Codes LogoExplain Codes Logo

Can Mockito capture arguments of a method called multiple times?

java
mockito
java-8
lambdas
Alex KataevbyAlex KataevยทJan 25, 2025
โšกTLDR

To capture the arguments of a method called multiple times in Mockito, start the mission by initializing the ArgumentCaptor.

ArgumentCaptor<YourType> argCaptor = ArgumentCaptor.forClass(YourType.class);

Calling the action sequence, direct your mock to perform the method of interest, then collect the arguments using argCaptor.getAllValues().

YourClass mock = Mockito.mock(YourClass.class); mock.someMethod(any(YourType.class)); // Can call this multiple times as needed ArgumentCaptor<YourType> argCaptor = ArgumentCaptor.forClass(YourType.class); verify(mock, times(n)).someMethod(argCaptor.capture()); List<YourType> capturedArgs = argCaptor.getAllValues(); // Action! ๐ŸŽฌ Captured all arguments in the film roll

Yep, argCaptor.getAllValues() is your film roll, holding every moment of action in the form of method arguments.

Beyond basic usage: Extreme captures

Custom argument matchers: Put on a mask ๐ŸŽญ

Java 8 users, rejoice! Matchers.argThat combined with lambdas will give you a more readable authentication sequence.

verify(mock, times(n)).someMethod(argThat(argument -> /* Hunting for impostors among arguments, Among Us style */));

In the line of action: Verifying method calls in sequence ๐Ÿš‚

When method call sequences matter, be the station master and control the call train using InOrder.

InOrder inOrder = inOrder(mock); inOrder.verify(mock).someMethod(argCaptor.capture()); // In order, sir!

Clean start: Priming with annotations ๐Ÿงน

Aim for cleaner code by using annotations for initialization.

@Captor ArgumentCaptor<YourType> argCaptor; // Meet our negotiator between the method and the captor @Before public void init() { MockitoAnnotations.initMocks(this); // Ready, set, annotate! }

Doesn't hurt to keep things tidy, does it?

Play it again, Sam: Asserting on a specific call ๐ŸŽง

Gotta catch that encore! To assert the argument from a specific call (yeah, the one you can't get out of your mind), grab all the values and stake your claim:

assertEquals("Expected Argument", capturedArgs.get(1)); // Playing the second song on loop

Spoiler: You might need to adjust the index to match your favorite tune.

Special cases and considerations

Conditional response and argument capturing

With ArgumentCaptor, you can create conditions on the fly while capturing arguments. Here's how:

when(mock.someMethod(argCaptor.capture())) .thenAnswer(invocation -> { YourType arg = invocation.getArgument(0); // Your magic trick with the captured wand return /* your magic result */; });

Type safety in capturing: Don't mix apples with oranges ๐ŸŽ๐ŸŠ

Ensure the captured argument types match your expectations to avoid unexpected ClassCastException (Not all fruits can be juiced without consequences!).

ArgumentCaptor<CorrectType> argCaptor = ArgumentCaptor.forClass(CorrectType.class);

Advance matching: Employ assertArg for custom assertions on arguments

assertArg(argument -> assertThat(argument, hasProperty("propertyName", equalTo("value")))); //Looking for a needle in the haystack

Add more power with Mockito's advanced features

Java 8 and Mockito are like Batman and Robin, bringing out the best in each other.

verify(mock, times(n)).someMethod(argThat(argument -> /* lambda based superpower activation */));