CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/maven-org-mockito--mockito-core

Mockito mock objects library core API and implementation for comprehensive Java unit testing

Pending
Overview
Eval results
Files

static-mocking.mddocs/

Static and Construction Mocking

This section covers advanced mocking capabilities introduced in Mockito 3.4+ for mocking static methods and object construction.

Static Method Mocking

MockedStatic Interface

Mock static methods within a controlled scope.

public static <T> MockedStatic<T> mockStatic(Class<T> classToMock)
public static <T> MockedStatic<T> mockStatic(Class<T> classToMock, String name)
public static <T> MockedStatic<T> mockStatic(Class<T> classToMock, Answer defaultAnswer)
public static <T> MockedStatic<T> mockStatic(Class<T> classToMock, MockSettings settings)

interface MockedStatic<T> extends AutoCloseable {
    <S> OngoingStubbing<S> when(Verification verification);
    <S> void verify(Verification verification);
    void verify(Verification verification, VerificationMode mode);
    void verifyNoMoreInteractions();
    void verifyNoInteractions();
    void clearInvocations();
    void close();
    void closeOnDemand();
    boolean isClosed();
}

Usage Examples:

// Basic static mocking
@Test
void testStaticMethod() {
    try (MockedStatic<Math> mockedMath = mockStatic(Math.class)) {
        // Stub static method
        mockedMath.when(() -> Math.max(1, 2)).thenReturn(5);
        
        // Use static method
        int result = Math.max(1, 2);
        assertEquals(5, result);
        
        // Verify static method call
        mockedMath.verify(() -> Math.max(1, 2));
    }
    // Static mock automatically closed
}

// Static mocking with argument matchers
@Test
void testStaticWithMatchers() {
    try (MockedStatic<Files> mockedFiles = mockStatic(Files.class)) {
        mockedFiles.when(() -> Files.exists(any(Path.class)))
                   .thenReturn(true);
        
        boolean exists = Files.exists(Paths.get("/any/path"));
        assertTrue(exists);
        
        mockedFiles.verify(() -> Files.exists(any(Path.class)));
    }
}

Partial Static Mocking

Mock only specific static methods while keeping others unchanged.

@Test
void testPartialStaticMocking() {
    try (MockedStatic<StringUtils> mockedUtils = mockStatic(StringUtils.class, CALLS_REAL_METHODS)) {
        // Only mock specific method
        mockedUtils.when(() -> StringUtils.isEmpty("test")).thenReturn(true);
        
        // This calls the real method
        String result = StringUtils.capitalize("hello");
        assertEquals("Hello", result);
        
        // This calls the mocked method
        boolean isEmpty = StringUtils.isEmpty("test");
        assertTrue(isEmpty);
    }
}

Construction Mocking

MockedConstruction Interface

Mock object construction and initialization.

public static <T> MockedConstruction<T> mockConstruction(Class<T> classToMock)
public static <T> MockedConstruction<T> mockConstruction(Class<T> classToMock, Function<Context, MockSettings> settingsFactory)
public static <T> MockedConstruction<T> mockConstruction(Class<T> classToMock, MockInitializer<T> mockInitializer)
public static <T> MockedConstruction<T> mockConstruction(Class<T> classToMock, Function<Context, MockSettings> settingsFactory, MockInitializer<T> mockInitializer)

interface MockedConstruction<T> extends AutoCloseable {
    List<T> constructed();
    void close();
    boolean isClosed();
    
    interface Context {
        int getCount();
        Class<?> getConstructedType();
        List<Class<?>> getParameterTypes();
        List<Object> getArguments();
    }
    
    interface MockInitializer<T> {
        void prepare(T mock, Context context) throws Throwable;
    }
}

Usage Examples:

// Basic construction mocking
@Test
void testConstructionMocking() {
    try (MockedConstruction<EmailService> mockedConstruction = 
         mockConstruction(EmailService.class)) {
        
        // Create objects - they will be mocked
        EmailService service1 = new EmailService("config1");
        EmailService service2 = new EmailService("config2");
        
        // Get constructed mocks
        List<EmailService> constructed = mockedConstruction.constructed();
        assertEquals(2, constructed.size());
        
        // Configure behavior
        when(service1.sendEmail(any())).thenReturn(true);
        when(service2.sendEmail(any())).thenReturn(false);
        
        // Test behavior
        assertTrue(service1.sendEmail("test"));
        assertFalse(service2.sendEmail("test"));
    }
}

// Construction mocking with initialization
@Test
void testConstructionWithInitializer() {
    try (MockedConstruction<DatabaseConnection> mockedConstruction = 
         mockConstruction(DatabaseConnection.class, (mock, context) -> {
             // Initialize each constructed mock
             when(mock.isConnected()).thenReturn(true);
             when(mock.getUrl()).thenReturn("mocked-url");
         })) {
        
        DatabaseConnection conn1 = new DatabaseConnection("real-url");
        DatabaseConnection conn2 = new DatabaseConnection("another-url");
        
        // Both connections have the same mocked behavior
        assertTrue(conn1.isConnected());
        assertTrue(conn2.isConnected());
        assertEquals("mocked-url", conn1.getUrl());
        assertEquals("mocked-url", conn2.getUrl());
    }
}

Advanced Construction Scenarios

Context-aware construction mocking with different behaviors.

@Test
void testContextAwareConstruction() {
    try (MockedConstruction<Logger> mockedConstruction = 
         mockConstruction(Logger.class, 
             context -> withSettings().name("logger-" + context.getCount()),
             (mock, context) -> {
                 String loggerName = "Logger#" + context.getCount();
                 when(mock.getName()).thenReturn(loggerName);
                 
                 // Different behavior based on constructor arguments
                 if (context.getArguments().contains("DEBUG")) {
                     when(mock.isDebugEnabled()).thenReturn(true);
                 } else {
                     when(mock.isDebugEnabled()).thenReturn(false);
                 }
             })) {
        
        Logger logger1 = new Logger("INFO");
        Logger logger2 = new Logger("DEBUG");
        
        assertEquals("Logger#1", logger1.getName());
        assertEquals("Logger#2", logger2.getName());
        assertFalse(logger1.isDebugEnabled());
        assertTrue(logger2.isDebugEnabled());
    }
}

Combining Static and Construction Mocking

Complex Mocking Scenarios

Combine different mocking approaches for comprehensive testing.

@Test
void testCombinedMocking() {
    try (MockedStatic<FileUtils> mockedFileUtils = mockStatic(FileUtils.class);
         MockedConstruction<FileReader> mockedConstruction = 
         mockConstruction(FileReader.class, (mock, context) -> {
             when(mock.read()).thenReturn("mocked content");
         })) {
        
        // Mock static utility
        mockedFileUtils.when(() -> FileUtils.exists("test.txt"))
                      .thenReturn(true);
        
        // Code under test
        FileProcessor processor = new FileProcessor();
        String result = processor.processFile("test.txt");
        
        // Verify both static and construction calls
        mockedFileUtils.verify(() -> FileUtils.exists("test.txt"));
        assertEquals(1, mockedConstruction.constructed().size());
        
        FileReader constructedReader = mockedConstruction.constructed().get(0);
        verify(constructedReader).read();
    }
}

Best Practices and Limitations

Resource Management

Always use try-with-resources for automatic cleanup.

// CORRECT - automatic cleanup
@Test
void testWithTryWithResources() {
    try (MockedStatic<System> mockedSystem = mockStatic(System.class)) {
        mockedSystem.when(() -> System.currentTimeMillis()).thenReturn(123456L);
        // Test code
    } // Automatically closed
}

// INCORRECT - manual cleanup required
@Test
void testWithManualCleanup() {
    MockedStatic<System> mockedSystem = mockStatic(System.class);
    try {
        mockedSystem.when(() -> System.currentTimeMillis()).thenReturn(123456L);
        // Test code
    } finally {
        mockedSystem.close(); // Must remember to close
    }
}

Thread Safety Considerations

Static mocks are not thread-safe and should be used carefully in parallel tests.

// Isolate static mocking in test methods
class ThreadSafeStaticTest {
    @Test
    void test1() {
        try (MockedStatic<Math> mock = mockStatic(Math.class)) {
            // Isolated static mock
        }
    }
    
    @Test
    void test2() {
        try (MockedStatic<Math> mock = mockStatic(Math.class)) {
            // Separate static mock instance
        }
    }
}

Performance Considerations

Static and construction mocking have performance overhead.

// Use sparingly and scope appropriately
@Test
void testPerformanceAware() {
    // Scope static mock to minimum necessary
    String result;
    try (MockedStatic<ExpensiveUtil> mock = mockStatic(ExpensiveUtil.class)) {
        mock.when(() -> ExpensiveUtil.compute(any())).thenReturn("cached");
        result = ExpensiveUtil.compute("input");
    }
    
    // Continue test without static mock overhead
    assertEquals("cached", result);
}

Limitations and Alternatives

Understanding when static/construction mocking isn't the best solution.

// Instead of mocking static utilities
class AvoidStaticMocking {
    // AVOID if possible
    @Test
    void testWithStaticMocking() {
        try (MockedStatic<UUID> mock = mockStatic(UUID.class)) {
            mock.when(UUID::randomUUID).thenReturn(fixedUuid);
            // Test
        }
    }
    
    // PREFER dependency injection
    @Test
    void testWithDependencyInjection() {
        UuidGenerator mockGenerator = mock(UuidGenerator.class);
        when(mockGenerator.generate()).thenReturn(fixedUuid);
        
        MyService service = new MyService(mockGenerator);
        // Test
    }
}

Install with Tessl CLI

npx tessl i tessl/maven-org-mockito--mockito-core

docs

additional-answers.md

additional-matchers.md

advanced-features.md

annotations.md

argument-matching.md

bdd-testing.md

index.md

mock-creation.md

static-mocking.md

stubbing.md

verification.md

tile.json