The thenAnswer
method in the Mockito framework is used to set a generic answer for a stubbed method. This allows you to define custom behavior for the method when it is called. The method belongs to the OngoingStubbing
interface, which is used to configure the behavior of mock methods.
Table of Contents
- Introduction
thenAnswer
Method Syntax- Examples
- Basic Usage
- Using a Custom Answer
- Real-World Use Case
- Conclusion
Introduction
Mockito is a popular library in Java for creating and managing mock objects. The thenAnswer
method, which belongs to the OngoingStubbing
interface, allows you to set a custom Answer
for a stubbed method. This can be useful when you need to define specific behavior for a method, such as returning a dynamic value or performing a side effect.
thenAnswer Method Syntax
Setting a Generic Answer for a Method
import org.mockito.stubbing.OngoingStubbing;
import org.mockito.stubbing.Answer;
OngoingStubbing<T> thenAnswer(Answer<?> answer)
Sets a generic answer for the method.
Parameters:
answer
: The customAnswer
to be used for the method.
Returns:
- An
OngoingStubbing
object that allows further configuration of the stubbed method.
Examples
Basic Usage
Set a custom answer for a stubbed method.
import static org.mockito.Mockito.*;
import org.mockito.stubbing.Answer;
import org.mockito.invocation.InvocationOnMock;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;
public class BasicThenAnswerTest {
@Test
void testThenAnswer() {
UserService mockUserService = mock(UserService.class);
// Set a custom answer
when(mockUserService.getUserDetails(anyString())).thenAnswer((Answer<String>) invocation -> {
String userId = invocation.getArgument(0);
return "User details for " + userId;
});
// Call the method
String details = mockUserService.getUserDetails("123");
assertEquals("User details for 123", details);
}
}
class UserService {
public String getUserDetails(String userId) {
return "Real user details for " + userId;
}
}
Using a Custom Answer
Define a custom Answer
class and use it with the thenAnswer
method.
import static org.mockito.Mockito.*;
import org.mockito.stubbing.Answer;
import org.mockito.invocation.InvocationOnMock;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;
public class CustomAnswerTest {
@Test
void testCustomAnswer() {
UserService mockUserService = mock(UserService.class);
// Define a custom Answer class
class CustomAnswer implements Answer<String> {
@Override
public String answer(InvocationOnMock invocation) {
String userId = invocation.getArgument(0);
return "Custom user details for " + userId;
}
}
// Set the custom answer
when(mockUserService.getUserDetails(anyString())).thenAnswer(new CustomAnswer());
// Call the method
String details = mockUserService.getUserDetails("456");
assertEquals("Custom user details for 456", details);
}
}
class UserService {
public String getUserDetails(String userId) {
return "Real user details for " + userId;
}
}
Real-World Use Case
Using Custom Answers in Service Mocks
In a real-world scenario, you might want to use custom answers to simulate complex behaviors in service methods. This allows you to provide dynamic responses based on the method arguments or simulate side effects.
import static org.mockito.Mockito.*;
import org.mockito.stubbing.Answer;
import org.mockito.invocation.InvocationOnMock;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;
interface PaymentService {
String processPayment(String orderId, double amount);
}
class PaymentServiceImpl implements PaymentService {
public String processPayment(String orderId, double amount) {
// Real implementation
return "Payment processed for order " + orderId;
}
}
public class PaymentServiceTest {
@Test
void testProcessPayment() {
PaymentService mockPaymentService = mock(PaymentService.class);
// Set a custom answer to simulate payment processing
when(mockPaymentService.processPayment(anyString(), anyDouble())).thenAnswer(new Answer<String>() {
@Override
public String answer(InvocationOnMock invocation) throws Throwable {
String orderId = invocation.getArgument(0);
double amount = invocation.getArgument(1);
if (amount > 1000) {
return "Payment declined for order " + orderId;
} else {
return "Payment processed for order " + orderId;
}
}
});
// Call the method with different arguments
String result1 = mockPaymentService.processPayment("123", 500);
String result2 = mockPaymentService.processPayment("456", 1500);
// Verify the results
assertEquals("Payment processed for order 123", result1);
assertEquals("Payment declined for order 456", result2);
}
}
In this example, the PaymentServiceTest
class uses Mockito’s thenAnswer
method with a custom Answer
to simulate different responses based on the payment amount. This allows the test to handle complex behaviors and verify that the service behaves as expected under different conditions.
Conclusion
The thenAnswer
method in Mockito is used for setting custom answers for stubbed methods. By using thenAnswer
, you can define specific behaviors for methods based on their arguments or simulate side effects. This helps ensure that your tests are accurate and comprehensive, allowing you to validate both real and mocked behavior.