Explain Codes LogoExplain Codes Logo

Mockito: Stubbing Methods That Return Type With Bounded Wild-Cards

java
mockito
generics
stubbing
Nikita BarsukovbyNikita Barsukov·Sep 8, 2024
TLDR

When stubbing a bounded wildcard generic method in Mockito, use any() and a proper type cast. Below is a short example for stubbing a Number return:

import static org.mockito.Mockito.doReturn; import static org.mockito.ArgumentMatchers.any; // Mocking in action YourClass mock = Mockito.mock(YourClass.class); // Stubbing with bounded wildcard magic doReturn(42).when(mock).<Number>getNumber(any());

Note: The <Number> type part ensures compatibility with the bounded wildcard, so we care about generics and type safety.

Stubbing generics - Decoded 👨‍💻

Using thenAnswer for dynamic results

If you're dealing with more complex control over the method's response, thenAnswer is your friend. It maintains type safety, especially useful dealing with generics:

import static org.mockito.Mockito.when; import static org.mockito.Mockito.any; import static org.mockito.Mockito.mock; import org.mockito.invocation.InvocationOnMock; import org.mockito.stubbing.Answer; // Who you gonna Mock? Ghostbusters! YourClass mock = Mockito.mock(YourClass.class); // Stubbing with thenAnswer when(mock.<List<? extends Number>>getList(any())).thenAnswer(new Answer<List<? extends Number>>() { @Override public List<? extends Number> answer(InvocationOnMock invocation) { // Returns a list of favorite numbers, spoiler: they're all prime! return new ArrayList<Integer>(Arrays.asList(2, 3, 5, 7, 11)); } });

Ensuring type-safe stubbing

Always try to, if not must, use thenAnswer to ensure type safety. In those scenarios where it's a do or die kind of situation, using doReturn is pardoned:

// BDD Style stubbing BDDMockito.willReturn(someList).given(mock).<List<? extends Sporty>>getSportySocks(any());

The flip side of doReturn

A method bypassing type checks? Sounds scary right? But doReturn can be the knight in shining armor in some wildcard situations at the cost of type safety:

import static org.mockito.Mockito.doReturn; // doReturn with wildcard doReturn(new ArrayList<String>()).when(mock).getList();

Visualization

The concept of stubbing methods with bounded wildcards in Mockito is like socks pairing:

Think about socks pairing: | Sock Type | Constraints | | ------------------------- | -------------- | | Ankle sock `<?>` | Any sock 🔓 | | Running sock `<? extends Sporty>` | Must be sporty 🏃‍♂️| Stubbing works like socks pairing: | Method Call | Machine Response | | --------------------------------- | ---------------------- | | getAnkleSock() | Returns any sock 🧦 | | getRunningSock() | Returns sporty sock 🏃‍♀️ |

Type-safe list with thenAnswer

For those methods returning lists with complex generics, you can use a similar pattern using thenAnswer:

import static org.mockito.Mockito.when; // Stubbing list return type when(mock.<List<? extends Number>>getNumbers()).thenAnswer((Answer<List<Integer>>) invocation -> Arrays.asList(1, 2, 3));

Collective wisdom

Sometimes, the best way to learn is to learn from others' mistakes. Do take a look at the Mockito Google group for more in-depth and challenging discussions.

Check out the manual

Mockito documentation is a goldmine. It isn't merely about the basics, but about how to think effectively in Mockito's context.