CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/maven-org-powermock--powermock-api-easymock

PowerMock API extension for EasyMock providing advanced mocking capabilities for static methods, constructors, final classes, and private methods through bytecode manipulation.

Pending
Overview
Eval results
Files

annotations.mddocs/

Annotation-Based Configuration

PowerMock provides annotation-based configuration that simplifies mock setup and reduces boilerplate code. This declarative approach improves test readability and maintainability while providing automatic mock lifecycle management.

Capabilities

Basic Mock Annotation

Automatically create and inject mock objects using field annotations.

/**
 * Annotation for automatic mock creation and injection.
 * Can be placed on fields to eliminate manual mock setup.
 */
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Mock {
    /**
     * Method names to mock for partial mocking.
     * If empty, all methods are mocked.
     */
    String[] value() default "";
    
    /**
     * Specific field name for targeted mock injection.
     * When set, mock will be assigned to the given field name in test subjects.
     */
    String fieldName() default "";
}

Usage Example

import org.powermock.api.easymock.annotation.Mock;
import org.powermock.api.extension.listener.AnnotationEnabler;
import org.powermock.core.classloader.annotations.PowerMockListener;

@PowerMockListener(AnnotationEnabler.class)
public class BasicAnnotationTest {
    
    @Mock
    private UserService userService;
    
    @Mock
    private OrderService orderService;
    
    private ShoppingCart shoppingCart;
    
    @Before
    public void setUp() {
        shoppingCart = new ShoppingCart(userService, orderService);
    }
    
    @Test
    public void testAnnotationBasedMocks() {
        // Mocks are automatically created and available
        expect(userService.getCurrentUser()).andReturn(new User("john"));
        expect(orderService.getPendingOrders("john")).andReturn(Arrays.asList(new Order("order1")));
        
        PowerMock.replayAll();
        
        List<Order> orders = shoppingCart.getUserOrders();
        
        assertEquals(1, orders.size());
        assertEquals("order1", orders.get(0).getId());
        
        PowerMock.verifyAll();
    }
}

Strict Mock Annotation

Create strict mocks that verify method call order using annotations.

/**
 * Annotation for automatic strict mock creation.
 * Strict mocks check the order of method calls.
 */
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
public @interface MockStrict {
    /**
     * Method names to mock for partial mocking.
     * If empty, all methods are mocked.
     */
    String[] value() default "";
}

Usage Example

@PowerMockListener(AnnotationEnabler.class)
public class StrictAnnotationTest {
    
    @MockStrict
    private DatabaseConnection connection;
    
    @MockStrict
    private Logger logger;
    
    private DataProcessor processor;
    
    @Before
    public void setUp() {
        processor = new DataProcessor(connection, logger);
    }
    
    @Test
    public void testStrictMockAnnotations() {
        // Strict mocks verify exact order of calls
        expect(logger.info("Starting connection")).andReturn(true);
        expect(connection.connect()).andReturn(true);
        expect(connection.executeQuery("SELECT * FROM data")).andReturn("data");
        expect(logger.info("Connection completed")).andReturn(true);
        expect(connection.disconnect()).andReturn(true);
        
        PowerMock.replayAll();
        
        // These calls must happen in exactly this order
        String result = processor.processData();
        
        assertEquals("Processed: data", result);
        PowerMock.verifyAll();
    }
}

Nice Mock Annotation

Create nice mocks that provide default return values for unexpected calls.

/**
 * Annotation for automatic nice mock creation.
 * Nice mocks allow unexpected method calls and return appropriate default values.
 */
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
public @interface MockNice {
    /**
     * Method names to mock for partial mocking.
     * If empty, all methods are mocked.
     */
    String[] value() default "";
}

Usage Example

@PowerMockListener(AnnotationEnabler.class)
public class NiceAnnotationTest {
    
    @MockNice
    private ConfigurationService configService;
    
    @MockNice
    private Logger logger;
    
    private ApplicationService appService;
    
    @Before
    public void setUp() {
        appService = new ApplicationService(configService, logger);
    }
    
    @Test
    public void testNiceMockAnnotations() {
        // Only set up the expectations you care about
        expect(configService.getProperty("app.name")).andReturn("TestApp");
        
        PowerMock.replayAll();
        
        // This call has explicit expectation
        String appName = appService.getApplicationName();
        assertEquals("TestApp", appName);
        
        // These calls don't have expectations but work with nice mocks
        appService.logStartup();           // logger methods return void (default)
        String version = appService.getVersion(); // Returns null (default for String)
        
        PowerMock.verifyAll();
    }
}

Partial Mocking with Annotations

Method-Specific Partial Mocking

Use annotations to create partial mocks that only mock specific methods.

@PowerMockListener(AnnotationEnabler.class)
public class PartialMockAnnotationTest {
    
    // Only mock the sendEmail and logEmailSent methods
    @Mock({"sendEmail", "logEmailSent"})
    private EmailService emailService;
    
    // Only mock the validateInput method
    @MockStrict({"validateInput"})
    private InputValidator validator;
    
    @Test
    public void testPartialMockingWithAnnotations() {
        // Set up expectations for mocked methods only
        expect(validator.validateInput("test input")).andReturn(true);
        expect(emailService.sendEmail("test@example.com", "Subject", "Body")).andReturn(true);
        emailService.logEmailSent("test@example.com");
        PowerMock.expectLastCall();
        
        PowerMock.replayAll();
        
        // Mocked methods
        boolean isValid = validator.validateInput("test input");
        boolean sent = emailService.sendEmail("test@example.com", "Subject", "Body");
        emailService.logEmailSent("test@example.com");
        
        // Non-mocked methods use real implementation
        String formatted = validator.formatInput("test input");  // Real behavior
        String serverInfo = emailService.getServerInfo();       // Real behavior
        
        assertTrue(isValid);
        assertTrue(sent);
        assertNotNull(formatted);
        assertNotNull(serverInfo);
        
        PowerMock.verifyAll();
    }
}

Field Name Targeting

Use the fieldName attribute to control mock injection into specific fields.

public class TestSubject {
    private UserService primaryUserService;
    private UserService backupUserService;
    private OrderService orderService;
}

@PowerMockListener(AnnotationEnabler.class)
public class FieldTargetingTest {
    
    // Inject into primaryUserService field specifically
    @Mock(fieldName = "primaryUserService")
    private UserService mockPrimaryUserService;
    
    // Inject into backupUserService field specifically  
    @Mock(fieldName = "backupUserService")
    private UserService mockBackupUserService;
    
    @Mock
    private OrderService orderService;
    
    @TestSubject
    private TestSubject testSubject;
    
    @Test
    public void testFieldNameTargeting() {
        // Set up different behaviors for different UserService instances
        expect(mockPrimaryUserService.getUserById(1)).andReturn(new User("primary-user"));
        expect(mockBackupUserService.getUserById(1)).andReturn(new User("backup-user"));
        expect(orderService.getOrdersByUser(1)).andReturn(Arrays.asList(new Order("order1")));
        
        PowerMock.replayAll();
        
        // testSubject now has different mocks injected into specific fields
        String result = testSubject.processUserWithBackup(1);
        
        assertTrue(result.contains("primary-user"));
        assertTrue(result.contains("backup-user"));
        
        PowerMock.verifyAll();
    }
}

Advanced Annotation Patterns

Combining Annotation Types

Mix different annotation types in the same test class for complex scenarios.

@PowerMockListener(AnnotationEnabler.class)
public class MixedAnnotationTest {
    
    @Mock
    private UserService userService;           // Regular mock
    
    @MockStrict
    private DatabaseConnection connection;     // Strict mock
    
    @MockNice
    private Logger logger;                     // Nice mock
    
    @Mock({"validatePermissions"})
    private SecurityService securityService;  // Partial mock
    
    @Test
    public void testMixedAnnotationTypes() {
        // Set up expectations based on mock types
        expect(userService.getUserById(1)).andReturn(new User("test"));
        
        // Strict mock - order matters
        expect(connection.connect()).andReturn(true);
        expect(connection.executeQuery(anyString())).andReturn("data");
        expect(connection.disconnect()).andReturn(true);
        
        // Partial mock - only mocked method needs expectation
        expect(securityService.validatePermissions("test", "read")).andReturn(true);
        
        // Nice mock - no explicit expectations needed
        
        PowerMock.replayAll();
        
        // Test code uses all mock types
        MyService service = new MyService(userService, connection, logger, securityService);
        String result = service.processUserData(1);
        
        assertNotNull(result);
        PowerMock.verifyAll();
    }
}

Annotation with Static and Constructor Mocking

Combine annotations with programmatic static and constructor mocking.

@PowerMockListener(AnnotationEnabler.class)
@PrepareForTest({FileUtils.class, DatabaseConnection.class})
public class HybridAnnotationTest {
    
    @Mock
    private UserService userService;
    
    @MockStrict
    private Logger logger;
    
    @Test
    public void testAnnotationsWithStaticMocking() throws Exception {
        // Annotation-based mocks
        expect(userService.getUserById(1)).andReturn(new User("test"));
        expect(logger.info("Processing user")).andReturn(true);
        
        // Programmatic static mocking
        PowerMock.mockStatic(FileUtils.class);
        expect(FileUtils.readFile("config.txt")).andReturn("config data");
        
        // Programmatic constructor mocking
        DatabaseConnection mockConnection = PowerMock.createMock(DatabaseConnection.class);
        PowerMock.expectNew(DatabaseConnection.class, "localhost").andReturn(mockConnection);
        expect(mockConnection.connect()).andReturn(true);
        
        PowerMock.replayAll();
        
        // Test code using both annotation and programmatic mocks
        HybridService service = new HybridService(userService, logger);
        String result = service.processUserWithConfig(1);
        
        assertNotNull(result);
        PowerMock.verifyAll();
    }
}

Configuration and Setup

Required Dependencies

Ensure proper annotation processing dependencies are available:

<dependency>
    <groupId>org.powermock</groupId>
    <artifactId>powermock-api-easymock</artifactId>
    <version>2.0.9</version>
    <scope>test</scope>
</dependency>

Test Class Configuration

Always include the @PowerMockListener(AnnotationEnabler.class) annotation:

@RunWith(PowerMockRunner.class)  // If using JUnit 4
@PowerMockListener(AnnotationEnabler.class)  // Required for annotation processing
@PrepareForTest({ClassesWithStaticMethods.class})  // If using static mocking
public class AnnotationConfiguredTest {
    // Test implementation
}

TestNG Configuration

For TestNG, use the PowerMock TestNG listener:

@PowerMockListener(AnnotationEnabler.class)
public class TestNGAnnotationTest extends PowerMockTestCase {
    
    @Mock
    private UserService userService;
    
    @Test
    public void testWithTestNG() {
        expect(userService.getUserById(1)).andReturn(new User("testng-user"));
        PowerMock.replayAll();
        
        // Test implementation
        
        PowerMock.verifyAll();
    }
}

Best Practices

Annotation Organization

@PowerMockListener(AnnotationEnabler.class)
public class WellOrganizedAnnotationTest {
    
    // Group related mocks together
    // Core service mocks
    @Mock private UserService userService;
    @Mock private OrderService orderService;
    
    // Infrastructure mocks
    @MockStrict private DatabaseConnection connection;
    @MockNice private Logger logger;
    
    // Partial mocks for complex services
    @Mock({"validate", "transform"}) 
    private DataProcessor dataProcessor;
    
    // Test subjects
    @TestSubject
    private ApplicationService applicationService;
    
    @Test
    public void testWellOrganized() {
        // Clear test implementation
    }
}

Mock Lifecycle Management

@PowerMockListener(AnnotationEnabler.class)
public class MockLifecycleTest {
    
    @Mock private UserService userService;
    @MockStrict private AuditLogger auditLogger;
    
    @Before
    public void setUpMocks() {
        // Additional setup after annotation processing
        // Mocks are already created by annotations
    }
    
    @After
    public void tearDownMocks() {
        // PowerMock automatically handles cleanup
        // Manual cleanup only if needed for special cases
        PowerMock.resetAll();
    }
    
    @Test
    public void testWithLifecycleManagement() {
        // Test implementation
        PowerMock.replayAll();
        // Test execution
        PowerMock.verifyAll();
    }
}

Important Notes

Annotation Processing Order

  1. PowerMock processes annotations before test method execution
  2. Mock objects are created and made available as field values
  3. Standard setup methods (@Before) run after annotation processing
  4. Test method executes with fully configured mocks

Integration with Dependency Injection

Annotations work well with dependency injection frameworks:

@PowerMockListener(AnnotationEnabler.class)
public class DIIntegrationTest {
    
    @Mock private DatabaseService databaseService;
    @Mock private EmailService emailService;
    
    @TestSubject  // Automatically injects mocks into this object
    private UserRegistrationService registrationService;
    
    @Test
    public void testWithDependencyInjection() {
        // Mocks are automatically injected into registrationService
        expect(databaseService.saveUser(anyObject(User.class))).andReturn(true);
        expect(emailService.sendWelcomeEmail(anyString())).andReturn(true);
        
        PowerMock.replayAll();
        
        boolean result = registrationService.registerUser("john@example.com", "password");
        
        assertTrue(result);
        PowerMock.verifyAll();
    }
}

Install with Tessl CLI

npx tessl i tessl/maven-org-powermock--powermock-api-easymock

docs

annotations.md

constructor-mocking.md

core-mocking.md

index.md

mock-control.md

partial-mocking.md

private-methods.md

reflection.md

static-mocking.md

tile.json