Mocking Static Blocks in Java

This is going to get into more "Advanced" JMockit. It turns out, you can redefine static initialization blocks in JMockit by creating a public void $clinit() method. So, instead of making this change

public class ClassWithStaticInit {
  static {
    staticInit();
  }

  private static void staticInit() {
    System.out.println("static initialized.");
  }
}

we might as well leave ClassWithStaticInit as is and do the following in the MockClassWithStaticInit:

public static class MockClassWithStaticInit {
  public void $clinit() {
  }
}

This will in fact allow us to not make any changes in the existing classes.


Occasionally, I find static initilizers in classes that my code depends on. If I cannot refactor the code, I use PowerMock's @SuppressStaticInitializationFor annotation to suppress the static initializer:

@RunWith(PowerMockRunner.class)
@SuppressStaticInitializationFor("com.example.ClassWithStaticInit")
public class ClassWithStaticInitTest {

    ClassWithStaticInit tested;

    @Before
    public void setUp() {
        tested = new ClassWithStaticInit();
    }

    @Test
    public void testSuppressStaticInitializer() {
        asserNotNull(tested);
    }

    // more tests...
}

Read more about suppressing unwanted behaviour.

Disclaimer: PowerMock is an open source project developed by two colleagues of mine.


PowerMock is another mock framework that extends EasyMock and Mockito. With PowerMock you can easily remove unwanted behavior from a class, for example a static initializer. In your example you simply add the following annotations to your JUnit test case:

@RunWith(PowerMockRunner.class)
@SuppressStaticInitializationFor("some.package.ClassWithStaticInit")

PowerMock does not use a Java agent and therefore does not require modification of the JVM startup parameters. You simple add the jar file and the above annotations.


Sounds to me like you are treating a symptom: poor design with dependencies on static initialization. Maybe some refactoring is the real solution. It sounds like you've already done a little refactoring with your staticInit() function, but maybe that function needs to be called from the constructor, not from a static initializer. If you can do away with static initializers period, you will be better off. Only you can make this decision (I can't see your codebase) but some refactoring will definitely help.

As for mocking, I use EasyMock, but I have run into the same issue. Side effects of static initializers in legacy code make testing difficult. Our answer was to refactor out the static initializer.