Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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?

like image 447
Cem Catikkas Avatar asked Sep 14 '08 05:09

Cem Catikkas


People also ask

Can you mock a static block?

Since static method belongs to the class, there is no way in Mockito to mock static methods. However, we can use PowerMock along with Mockito framework to mock static methods.

Can we mock a static class in Java?

Mocking a No Argument Static Method 0, we can use the Mockito. mockStatic(Class<T> classToMock) method to mock invocations to static method calls. This method returns a MockedStatic object for our type, which is a scoped mock object.

Can static classes be mocked?

Because there is no instance variable, the class name itself should be used to access the members of a static class. The powerful capabilities of the feature-rich JustMock framework allow you to mock static classes and calls to static members like methods and properties, set expectations and verify results.

Why should we not mock static methods?

If you need to mock a static method, it is a strong indicator for a bad design. Usually, you mock the dependency of your class-under-test. If your class-under-test refers to a static method - like java.


1 Answers

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.

like image 179
Jan Kronquist Avatar answered Sep 21 '22 07:09

Jan Kronquist