← Back to Home

Module 3: Static Methods

Module Overview

Understand static methods, when to use them, and how to properly test code that uses static methods.

Understanding Static Methods and Testing

Static methods in Java belong to the class rather than instances of the class. They can be called directly on the class without creating an object. While convenient, static methods present unique challenges for testing.

This module explores the proper use of static methods, static variables, and how to test code that relies on static functionality.

// Example of a static utility method
public class MathUtils {
    public static int add(int a, int b) {
        return a + b;
    }
}

// Using the static method
int sum = MathUtils.add(5, 3); // Returns 8

Learning Objectives

Testing Static Methods

Testing code that uses static methods requires special techniques:

  • Mockito (newer versions): Can mock static methods with the MockedStatic feature
  • PowerMock: Used with older Mockito versions to mock static methods
  • Refactoring: Sometimes the best approach is to change the design to avoid static dependencies
// Example of testing with static mocking (Mockito 3.4.0+)
@Test
public void testStaticMethod() {
    // Given
    try (MockedStatic<DateUtils> mockedStatic = mockStatic(DateUtils.class)) {
        // Setup static mock behavior
        mockedStatic.when(() -> DateUtils.getCurrentDate()).thenReturn("2023-04-15");
        
        // When
        String result = myService.getFormattedCurrentDate();
        
        // Then
        assertEquals("Current date: 2023-04-15", result);
        
        // Verify static method was called
        mockedStatic.verify(() -> DateUtils.getCurrentDate());
    }
}

Constants and Refactoring

Static final fields (constants) provide a way to share immutable values across your application:

public class AppConstants {
    // Constants are typically uppercase with underscores
    public static final int MAX_LOGIN_ATTEMPTS = 5;
    public static final String API_VERSION = "v1.2";
    public static final double TAX_RATE = 0.07;
}

// Using constants
if (loginAttempts >= AppConstants.MAX_LOGIN_ATTEMPTS) {
    lockAccount();
}

When refactoring to improve testability, consider dependency injection to replace static dependencies:

// Before refactoring
public class WeatherService {
    public String getTemperature(String city) {
        return WeatherAPI.getCurrentTemperature(city);
    }
}

// After refactoring
public class WeatherService {
    private final WeatherAPI weatherAPI;
    
    public WeatherService(WeatherAPI weatherAPI) {
        this.weatherAPI = weatherAPI;
    }
    
    public String getTemperature(String city) {
        return weatherAPI.getCurrentTemperature(city);
    }
}

Resources