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
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.
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.
You could write your test code in Groovy and easily mock the static method using metaprogramming.
Math.metaClass.'static'.max = { int a, int b ->
a + b
}
Math.max 1, 2
If you can't use Groovy, you will really need to refactoring the code (maybe to inject something like a initializator).
Kind Regards
Not really an answer, but just wondering - isn't there any way to "reverse" the call to Mockit.redefineMethods
?
If no such explicit method exists, shouldn't executing it again in the following fashion do the trick?
Mockit.redefineMethods(ClassWithStaticInit.class, ClassWithStaticInit.class);
If such a method exists, you could execute it in the class' @AfterClass
method, and test ClassWithStaticInitTest
with the "original" static initializer block, as if nothing has changed, from the same JVM.
This is just a hunch though, so I may be missing something.