Explain Codes LogoExplain Codes Logo

How to verify multiple method calls with different params

java
argument-capturing
mockito
unit-testing
Anton ShumikhinbyAnton Shumikhin·Feb 22, 2025
TLDR

Harness the power of Mockito's verify() functionality for validating distinct method invocations with unique parameters:

import static org.mockito.Mockito.*; MyClass myMock = mock(MyClass.class); myMock.myMethod("param1"); myMock.myMethod("param2"); // Verification 101: Always check your method calls verify(myMock).myMethod("param1"); // "param1" checked in ✔️ verify(myMock).myMethod("param2"); // "param2" checked in ✔️

Emphasize on individual verify() calls for each parameter to confirm that the expected interactions have taken place.

Advanced scenarios: Argument capturing and ordering specifications

Your basic test requirements can be served well by simple verification. However, for more complex scenario handling, ArgumentCaptor and InOrder come into play.

Capturing arguments for inspection

This technique allows you to verify the argument values a method was invoked with. Let's use ArgumentCaptor:

ArgumentCaptor<String> argumentCaptor = ArgumentCaptor.forClass(String.class); verify(myMock).myMethod(argumentCaptor.capture()); // Say hello to your captured arguments! List<String> capturedArguments = argumentCaptor.getAllValues();

For those who crave order in chaos

If there's a certain sequence to the method calls that must be adhered to, Mockito's InOrder verification is your knight in shining armor.

InOrder inOrder = inOrder(myMock); inOrder.verify(myMock).myMethod("firstCall"); // First in, first out inOrder.verify(myMock).myMethod("secondCall"); // Two's company

Ensure the actual execution order matches the order of verify() for mission success.

Practical use cases and robust solutions

Writing reliable unit tests is both an art and science. Especially when dealing with unique edge cases or ordered sequences, certain nuances need to be considered.

Ignoring trivial pursuits

Sometimes, certain parameters are not integral to your verification process. Mockito's any() serves as the perfect wildcard matcher:

verify(myMock).myMethod(anyString(), eq("specificValue")); // Stubbornly only cares about "specificValue"

Here, with anyString(), we are not stressing over some arguments while focusing on others.

Assert first, debug later

Comparing the captured and expected values is crucial to aligning actual behavior with expectations:

assertEquals("Expected Param", argumentCaptor.getValue()); assertEquals(2, argumentCaptor.getAllValues().size());

On the boundaries of unit testing

Certain best practices to heed and pitfalls to avoid always come in handy to build robust, scalable tests.

Mock responsibly

Exercise caution while mocking external dependencies. They can lead to fragile tests sensitive to changes in external code.

Avoid the mismatched socks problem

When verifying, use the correct types to avoid any unpleasant surprises:

verify(myMock).myMethod(isA(MyType.class)); // MyType, not MyRandomType

Double-check your cart before checkout

Always ensure that you're verifying the right method with the correct arguments. It's a quick sanity check to prevent overlooked bugs:

verify(myMock, times(1)).myMethod("expectedParam");

Order up!

For accurate tests, respect the order of verify(). Especially when using InOrder verifications, sequence matters!