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?
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.
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.
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.
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With