Explain Codes LogoExplain Codes Logo

Mockito: doAnswer Vs thenReturn

java
mockito
testing
stubbing
Alex KataevbyAlex Kataev·Dec 4, 2024
TLDR

When you have a fixed value to return, apply thenReturn() for clean stubbing:

// Like a trusty loyal dog, always fetching the same stick when(mock.someMethod()).thenReturn(value);

For a more flexible approach where you need to apply logic to the response, say hello to doAnswer():

// Like a cat, a bit more unpredictable but way more fun doAnswer(invocation -> "response based on " + invocation.getArgument(0)) .when(mock).someMethod(any());

The art of choosing the suitable stubbing

Static return values? Use thenReturn

thenReturn() is your reliable friend for consistent stubbing -- it'll dutifully return the same response each time:

// It's like eating pizza every day. Predictable and satisfying! when(mock.myMethod()).thenReturn(myFixedValue);

Where methods are called multiple times within the same test, thenReturn() lets you stage dramatic performances by returning different preset values each time:

// Like a TV series with predictable plot twists when(mock.myMethod()).thenReturn(firstValue, secondValue, thirdValue);

Stubbing with a dynamic twist using doAnswer

doAnswer() becomes the protagonist when a dynamic response is your quest. With doAnswer(), your stub can craft responses based on input like a master chef whipping up custom dishes:

// Like making a cocktail, mixing ingredients to get a unique flavor doAnswer(invocation -> { Integer input = invocation.getArgument(0); return input * 2; // Craft the response }).when(mock).myMethod(anyInt());

doAnswer() also allows side quests during method invocation such as modifying state or validating inputs.

Stubbing void methods with doAnswer

doAnswer() comes to the rescue for void methods. It allows you to venture through the twisty palaces of methods that change state or generate side effects like incomplete blueprints that still gets the job done:

// Like following a map with some areas marked "Here be dragons" doAnswer(invocation -> { System.out.println("Method called with arguments: " + Arrays.toString(invocation.getArguments())); return null; // Void methods return empty loot }).when(mock).voidMethod(any());

Spying with doAnswer

When you're spying on objects, doAnswer() ensures you can stub methods without triggering real behavior. It's a perfect stealth approach to prevent your test cover from being blown:

// Like being a ninja, leave no trace behind doAnswer(invocation -> "mocked value").when(spy).myRealMethod();

Unraveling the enigma of doReturn

doReturn() offers an option to thenReturn() which is like switching to Easy mode. It's useful when you need to guarantee that a spied method's actual logic does not run while stubbing:

// Like a secret bypass, to avoid the dragon doReturn("mocked value").when(spy).myRealMethod();

Comprehending through usage twists

Simulating exceptions with doAnswer

doAnswer() allows you to simulate how your code reacts to exceptions. It's like a simulated war game for your code:

doAnswer(invocation -> { if ("bad".equals(invocation.getArgument(0))) { throw new IllegalArgumentException("Please, no vegetables!"); } return "good response"; }).when(mock).someMethod(anyString());

Simulating latency

To simulate slow responses or time delays, doAnswer() offers a vehicle into the future:

doAnswer(invocation -> { Thread.sleep(1000L); // Delay for dramatizing suspense return "Hello from the future!"; }).when(mock).someMethod();

Advanced response logic

When the scenario permits extra computations or external states, doAnswer() becomes the key to your creative kingdom:

doAnswer(invocation -> { if (someExternalCondition) { return "condition met"; } return "default response"; }).when(mock).someMethod();