Mockito mock objects library core API and implementation for comprehensive Java unit testing
—
This section covers advanced Mockito features including session management, framework integration, custom plugins, and debugging utilities.
Manage mock lifecycle with automatic cleanup and strictness control.
public static MockitoSessionBuilder mockitoSession()
public static MockitoSession mockitoSession(Object... testClassInstances)
interface MockitoSession {
void setStrictness(Strictness strictness);
void finishMocking();
void finishMocking(Throwable failure);
}
interface MockitoSessionBuilder {
MockitoSessionBuilder name(String name);
MockitoSessionBuilder strictness(Strictness strictness);
MockitoSessionBuilder logger(MockitoSessionLogger logger);
MockitoSessionBuilder initMocks(Object... testClassInstances);
MockitoSession startMocking();
}Usage Examples:
class SessionManagedTest {
@Mock private UserService userService;
@Mock private EmailService emailService;
@Test
void testWithSession() {
MockitoSession session = mockitoSession()
.initMocks(this)
.name("UserRegistrationTest")
.strictness(Strictness.STRICT_STUBS)
.startMocking();
try {
// Test code with automatic mock management
given(userService.createUser(any())).willReturn(newUser);
// Test execution
registrationService.registerUser("john@example.com");
// Verification
then(userService).should().createUser(any());
} finally {
session.finishMocking(); // Validates unused stubs, etc.
}
}
@Test
void testWithTryWithResources() {
try (MockitoSession session = mockitoSession()
.initMocks(this)
.strictness(Strictness.LENIENT)
.startMocking()) {
// Test code - session automatically finished
}
}
}Implement custom logging for session events.
interface MockitoSessionLogger {
void log(String hint);
}Usage Example:
class CustomSessionLogger implements MockitoSessionLogger {
private final List<String> logs = new ArrayList<>();
@Override
public void log(String hint) {
logs.add("[MOCKITO] " + hint);
System.out.println(hint);
}
public List<String> getLogs() {
return Collections.unmodifiableList(logs);
}
}
@Test
void testWithCustomLogger() {
CustomSessionLogger logger = new CustomSessionLogger();
try (MockitoSession session = mockitoSession()
.logger(logger)
.startMocking()) {
// Test code
}
// Check logged hints
assertThat(logger.getLogs()).contains("Unused stubbings detected");
}Access to framework-level functionality and plugins.
public static MockitoFramework framework()
interface MockitoFramework {
MockitoPlugins getPlugins();
InvocationFactory getInvocationFactory();
MockitoSession mockitoSession();
void clearInlineMocks();
}Usage Examples:
@Test
void testFrameworkIntegration() {
MockitoFramework framework = framework();
// Access plugin system
MockMaker mockMaker = framework.getPlugins().getMockMaker();
System.out.println("Mock maker: " + mockMaker.getClass().getSimpleName());
// Create invocation factory for advanced scenarios
InvocationFactory factory = framework.getInvocationFactory();
// Clear inline mocks (useful for cleanup)
framework.clearInlineMocks();
}Access and configure Mockito plugins.
interface MockitoPlugins {
MockMaker getMockMaker();
AnnotationEngine getAnnotationEngine();
StackTraceCleanerProvider getStackTraceCleanerProvider();
InstantiatorProvider getInstantiatorProvider();
}Usage Example:
@Test
void testPluginAccess() {
MockitoPlugins plugins = framework().getPlugins();
// Check which mock maker is being used
MockMaker mockMaker = plugins.getMockMaker();
if (mockMaker instanceof InlineMockMaker) {
System.out.println("Using inline mock maker - can mock final classes");
}
// Access annotation engine
AnnotationEngine engine = plugins.getAnnotationEngine();
System.out.println("Annotation engine: " + engine.getClass().getSimpleName());
}Tools for debugging mock usage and detecting issues.
public static void validateMockitoUsage()
public static String mockitoInfo()Usage Examples:
@Test
void testWithValidation() {
List<String> mockList = mock(List.class);
// Setup and use mocks
when(mockList.get(0)).thenReturn("first");
mockList.get(0);
// Validate usage - throws exception if problems detected
validateMockitoUsage();
}
@Test
void testDebuggingInfo() {
// Get Mockito version and configuration info
String info = mockitoInfo();
System.out.println(info);
// Useful for troubleshooting environment issues
assertThat(info).contains("Mockito version");
}Detailed inspection of mock objects and their state.
@Test
void testMockInspection() {
List<String> mockList = mock(List.class);
// Use mock
when(mockList.get(0)).thenReturn("stubbed");
mockList.get(0);
mockList.size();
MockingDetails details = mockingDetails(mockList);
// Inspect invocations
Collection<Invocation> invocations = details.getInvocations();
System.out.println("Number of invocations: " + invocations.size());
for (Invocation invocation : invocations) {
System.out.println("Method: " + invocation.getMethod().getName());
System.out.println("Arguments: " + Arrays.toString(invocation.getArguments()));
System.out.println("Location: " + invocation.getLocation());
}
// Inspect stubbings
Collection<StubbingInfo> stubbings = details.getStubbings();
for (StubbingInfo stubbing : stubbings) {
System.out.println("Stubbing used: " + stubbing.wasUsed());
}
}Configure how strict Mockito should be about mock usage.
enum Strictness {
LENIENT, // Most permissive
WARN, // Warn about potential issues
STRICT_STUBS // Fail on unused stubs
}Usage Examples:
class StrictnessTest {
@Test
void testLenientMode() {
// Lenient - unused stubs don't cause failures
List<String> mock = mock(List.class, withSettings().lenient());
when(mock.get(0)).thenReturn("never used"); // Won't cause test failure
when(mock.size()).thenReturn(5);
assertEquals(5, mock.size()); // Only this stub is used
// Test passes even though get(0) stub is unused
}
@Test
void testStrictMode() {
// Strict mode - all stubs must be used
List<String> mock = mock(List.class, withSettings().strictness(Strictness.STRICT_STUBS));
when(mock.size()).thenReturn(5);
assertEquals(5, mock.size());
// If we had unused stubs, test would fail
}
@Test
void testSessionStrictness() {
try (MockitoSession session = mockitoSession()
.strictness(Strictness.STRICT_STUBS)
.startMocking()) {
List<String> mock = mock(List.class);
when(mock.get(0)).thenReturn("must be used");
// Must use all stubs
mock.get(0);
} // Session validates on close
}
}Get suggestions for improving test quality.
class MockitoHint {
public static String get() { /* implementation */ }
}Create sophisticated mock behaviors.
class AdvancedAnswers {
// Delegating answer that forwards to real object selectively
public static class SelectiveDelegateAnswer implements Answer<Object> {
private final Object delegate;
private final Set<String> methodsToDelegate;
public SelectiveDelegateAnswer(Object delegate, String... methods) {
this.delegate = delegate;
this.methodsToDelegate = Set.of(methods);
}
@Override
public Object answer(InvocationOnMock invocation) throws Throwable {
String methodName = invocation.getMethod().getName();
if (methodsToDelegate.contains(methodName)) {
return invocation.getMethod().invoke(delegate, invocation.getArguments());
}
return Answers.RETURNS_DEFAULTS.answer(invocation);
}
}
// Answer that tracks call counts
public static class CountingAnswer<T> implements Answer<T> {
private final AtomicInteger callCount = new AtomicInteger(0);
private final T returnValue;
public CountingAnswer(T returnValue) {
this.returnValue = returnValue;
}
@Override
public T answer(InvocationOnMock invocation) {
callCount.incrementAndGet();
return returnValue;
}
public int getCallCount() {
return callCount.get();
}
}
@Test
void testCustomAnswers() {
UserService mockService = mock(UserService.class);
// Use selective delegate answer
UserService realService = new UserService();
SelectiveDelegateAnswer answer = new SelectiveDelegateAnswer(realService, "validateUser");
when(mockService.validateUser(any())).thenAnswer(answer);
when(mockService.createUser(any())).thenReturn(mockUser);
// Use counting answer
CountingAnswer<Boolean> countingAnswer = new CountingAnswer<>(true);
when(mockService.isActive(any())).thenAnswer(countingAnswer);
// Test
mockService.isActive(user1);
mockService.isActive(user2);
assertEquals(2, countingAnswer.getCallCount());
}
}Collect verification failures instead of failing immediately.
interface VerificationCollector extends TestWatcher, AfterEachCallback {
// Collects verification failures for batch reporting
}
public static VerificationCollector collector()Usage Example:
@ExtendWith(MockitoExtension.class)
class CollectorTest {
@RegisterExtension
static VerificationCollector collector = MockitoJUnit.collector();
@Mock private UserService userService;
@Mock private EmailService emailService;
@Test
void testWithCollector() {
// Test code that might have multiple verification failures
userService.createUser("test");
// These verifications are collected, not immediately failing
collector.verify(() -> verify(userService).createUser("wrong-param"));
collector.verify(() -> verify(emailService).sendEmail(any()));
// All failures reported at end of test
}
}Choose appropriate mock maker for performance needs.
class MockMakerTest {
@Test
void testInlineMockMaker() {
// Check if inline mock maker is available
if (framework().getPlugins().getMockMaker() instanceof InlineMockMaker) {
// Can mock final classes and methods
final class FinalClass {
final String getValue() { return "real"; }
}
FinalClass mock = mock(FinalClass.class);
when(mock.getValue()).thenReturn("mocked");
assertEquals("mocked", mock.getValue());
}
}
@Test
void testSubclassMockMaker() {
// Force subclass mock maker for testing
UserService mock = mock(UserService.class, withSettings()
.mockMaker("subclass"));
// Works with non-final classes only
when(mock.getUsers()).thenReturn(Collections.emptyList());
}
}Best practices for memory usage with mocks.
class MemoryManagementTest {
@Test
void testMockCleanup() {
List<Object> mocks = new ArrayList<>();
// Create many mocks
for (int i = 0; i < 1000; i++) {
mocks.add(mock(UserService.class));
}
// Clear references
mocks.clear();
// Clear inline mocks if using inline mock maker
framework().clearInlineMocks();
// Force garbage collection for testing
System.gc();
}
}Install with Tessl CLI
npx tessl i tessl/maven-org-mockito--mockito-core