Yes, it is possible to mock a method with specific return values using Mockito's mock() method. Mockito, a popular mocking framework in Java, allows creating mock objects on which specific method calls can be stubbed to return desired values. Below is a detailed explanation of how to achieve this, including various features and techniques related to mocking methods to return specific values, along with examples.
Basic Mocking and Stubbing Return Values
Mockito's core feature is mocking objects and stubbing method calls to return specific results. You start by creating a mock object of a given class using Mockito.mock():
java
MyClass myMock = Mockito.mock(MyClass.class);
Then, you can specify return values for specific method calls using the `when(...).thenReturn(...)` pattern:
java
when(myMock.someMethod()).thenReturn(expectedValue);
Here, whenever `someMethod()` is called on `myMock`, it returns `expectedValue`. This is the simplest way to control mocked method output.
Examples of Mocking Specific Return Values
java
List mockedList = Mockito.mock(List.class);
// stub method
when(mockedList.get(0)).thenReturn("first element");
when(mockedList.get(1)).thenReturn("second element");
// calls to mockedList.get(0) and get(1) will return specified values
System.out.println(mockedList.get(0)); // prints "first element"
System.out.println(mockedList.get(1)); // prints "second element"
Mocking Different Return Values on Sequential Calls
Sometimes, it's necessary to return different values on consecutive calls of the same method. Mockito supports chaining return values in `thenReturn()`:
java
when(myMock.someMethod()).thenReturn(value1).thenReturn(value2);
On the first call, `someMethod()` returns `value1`, on the second call, it returns `value2`, and subsequent calls return `value2` by default.
For example:
java
when(mockedList.size()).thenReturn(10).thenReturn(20);
System.out.println(mockedList.size()); // returns 10
System.out.println(mockedList.size()); // returns 20
System.out.println(mockedList.size()); // returns 20
Throwing Exceptions Instead of Returning Values
You can configure mocked methods to throw exceptions instead of returning values, useful for testing error handling:
java
when(myMock.someMethod()).thenThrow(new RuntimeException("error message"));
Mocking with Argument Matchers
Mockito allows mocking a method's return value based on specific argument matchers:
java
when(myMock.someMethod(anyString())).thenReturn("result");
when(myMock.someMethod(eq("specific"))).thenReturn("specific result");
This lets you control what is returned depending on method parameters.
Partial Mocking with `thenCallRealMethod()`
In scenarios where you want to mock some methods but execute the real implementation for others, `thenCallRealMethod()` can be used:
java
MyClass myMock = mock(MyClass.class);
when(myMock.methodToMock()).thenReturn(mockedValue);
when(myMock.methodToRunReal()).thenCallRealMethod();
This is useful for creating partial mocks where some methods retain real behavior.
Using `spy()` for Partial Mocking
The `spy()` method wraps an actual instance and lets you stub specific methods while others run as normal:
java
MyClass realObject = new MyClass();
MyClass spyObject = spy(realObject);
when(spyObject.methodToMock()).thenReturn(mockedValue);
// Other methods on spyObject execute real methods
Custom Answers for Dynamic Return Values
Mockito also supports dynamic return values using the `Answer` interface for more complex stubbing:
java
when(myMock.someMethod(anyString())).thenAnswer(new Answer() {
public String answer(InvocationOnMock invocation) {
Object[] args = invocation.getArguments();
String arg = (String) args[0];
return "Hello " + arg;
}
});
This approach lets you define logic to build return values at runtime based on arguments.
Using `mock()` with Custom Answers
The `mock()` method in Mockito also accepts an `Answer` argument to define default behavior for all unstubbed methods:
java
MyClass myMock = mock(MyClass.class, new Answer() {
public Object answer(InvocationOnMock invocation) {
// Provide custom default return value logic here
return someValue;
}
});
This approach is especially useful when working with legacy or complex code, allowing you to configure global default return values on mocks.
Deep Stubbing
If the methods return other mockable objects, deep stubs let you mock chained calls:
java
MyClass myMock = mock(MyClass.class, RETURNS_DEEP_STUBS);
when(myMock.getSomeObject().someMethod()).thenReturn(someValue);
Notes on Using `mock()` for Custom Return Values
- `mock()` returns a mock object of the specified type.
- You can then stub methods on the mock using `when().thenReturn()` or similar constructs.
- Each stubbed method can have specific return values.
- This applies equally to void methods (using doNothing(), doThrow(), etc.) and return-value methods.
- The behavior of the mock object can be finely customized and chained for sequential calls.
Common Patterns and Pitfalls
- Multiple calls to `when(...).thenReturn(...)` on the same method override previous stubs for that method unless chaining is used.
- Use `doReturn(...)` for mocking spy objects to avoid calling real methods during stubbing.
- Rebuild mocks or reset them between tests to avoid state leakage.
- Avoid excessive use of partial mocks; prefer designing testable code with dependency injection.
Summary of Usage
- Create a mock with `mock()`.
- Stub methods with `when(mock.method()).thenReturn(value)` for specific return values.
- Chain returns for sequential calls with `thenReturn(value1).thenReturn(value2)`.
- Use argument matchers to control behavior for different inputs.
- Use `thenCallRealMethod()` or `spy()` to partially mock behavior.
- Implement `Answer` for dynamic or complex return logic.
- Reset mocks between tests if needed.