Sunday, September 14, 2008

Mocking Static Blocks in Java

My motto for Java is "just because Java has static blocks, it doesn't mean that you should be using them." Jokes aside, there are a lot of tricks in Java that make testing a nightmare. Two of the most I hate are Anonymous Classes and Static Blocks. We have a lot of legacy code that make use of Static Blocks and these are one of the annoying points in our push in writing unit tests. Our goal is to be able to write unit tests for classes that depend on this static initialization with minimal code changes.

So far my suggestion to my colleagues is to move the body of the static block into a private static method and call it staticInit. This method can then be called from within the static block. For unit testing another class that depends on this class could easily mock staticInit with JMockit to not do anything. Let's see this in example.

public class ClassWithStaticInit {
 
static {
   
System.out.println("static initializer.");
 
}
}
Will be changed to
public class ClassWithStaticInit {
 
static {
    staticInit
();
 
}

 
private static void staticInit() {
   
System.out.println("static initialized.");
 
}
}
So that we can do the following in a JUnit.
public class DependentClassTest {
 
public static class MockClassWithStaticInit {
   
public static void staticInit() {
   
}
 
}

 
@BeforeClass
 
public static void setUpBeforeClass() {
   
Mockit.redefineMethods(ClassWithStaticInit.class, MockClassWithStaticInit.class);
 
}
}
However this solution also comes with its own problems. You can't run DependentClassTest and ClassWithStaticInitTest on the same JVM since you actually want the static block to run for ClassWithStaticInitTest.

What would be your way of accomplishing this task? Or any better, non-JMockit based solutions that you think would work cleaner? Please follow the discussion at StackOverflow.com.

1 comment:

Justin said...

Nice info... Hope to learn more....