I am trying to have RunWith(PowerMockRunner.class) working with my existing package annotation.
Versions:
powermock 1.4.12 mockito 1.9.0 junit 4.8.2
package-info.java // this is for the package annotation
@TestAnnotation(version="1.0")
package com.smin.dummy;
TestAnnotation.java // this is the the metadata annotation class for package "com.smin.dummy"
package com.smin.dummy;
import java.lang.annotation.*;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.PACKAGE)
public @interface TestAnnotation {
String version();
}
A.java
package com.smin.dummy;
public class A {
private static Package myPackage;
private static TestAnnotation version;
static {
myPackage = TestAnnotation.class.getPackage();
version = myPackage.getAnnotation(TestAnnotation.class);
}
public static String getVersion() {
return version.version();
}
}
MockA.java
package com.smin.dummy;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import com.smin.dummy.A;
@RunWith(PowerMockRunner.class) //comment out this line to see the difference
@PrepareForTest(A.class)
public class MockA {
@Test
public void test_mocked() throws Throwable {
String thisVersion = A.getVersion();
System.out.println(thisVersion);
}
}
In the unitest MockA.java, if I don't use RunWith(PowerMockRunner.class)
, I will get the thisVersion
printed 0.1
as expected. But after adding RunWith(PowerMockRunner.class)
, thisVersion
turns into null
. I suspect PowerMockRunner is doing some funny thing with the package annotation here, anybody has any idea? see the mini version of my code below:
@RunWith(PowerMockRunner.class)
. It appears Powermock is setting its own class loader, and this is how the magic of injecting the mocked class into the test case happens. I'm affraid you're right, the package of the class generated by powermock is no longer annotated as it should be. – Alban, and found out that the annotation you set on the packageis actually replaced by a proxy. So
getAnnotation(TestAnnotation.class)` returns null. If you loop over the list of annotations on the package, there is no annotation that is an instance or a super class instance of TestAnnotation.class. The annotation that actually is on the package is a proxy. I failed to find a way to instruct MockClassLoader to defer to the system class loader the loading of any class other than A. According to the java doc, it's possible. – Alban