Search code examples
javamockitoclassloaderjunit4powermockito

Singleton returning new instance when accessed from test method


I am using Junit 4.12 with PowerMock 1.6 with Mockito. I have also used PowerMockRule library as described here. I am trying to execute initialization code for all of my test cases exactly once as described in this SO Thread. Its executing the initialization code exactly one time however, if I do ServiceInitializer.INSTANCE inside test method it returns me new object. I am not able to understand this behavior. Does anyone have any idea why this is happening? If I execute my code without PowerMockRule Library and run my test with PowerMockRunner then it works fine but in that case my ClassRule is not getting executed.

    public class ServiceInitializer extends ExternalResource {
      public static final TestRule INSTANCE = new ServiceInitializer();
      private final AtomicBoolean started = new AtomicBoolean();

      @Override protected void before() throws Throwable {
        if (!started.compareAndSet(false, true)) {
          return;
        }
        // Initialization code goes here
        System.out.println("ServiceInitializationHelper:"+this); //Print Address @3702c2f1
      }

      @Override protected void after() {
      }
    }




    class BaseTest{
            @Rule
            public PowerMockRule powerMockRule = new PowerMockRule();

              @ClassRule
              public static final TestRule serviceInitializer = ServiceInitializer.INSTANCE;

              @Before
              public final void preTest() {
                // some code
              }

              @After
              public final void postTest() {
                //some code
              }
    }


@PrepareForTest({MyClass.class})
public class MyTest extends BaseTest {
      @Test
      public void testMethodA_1(){
            System.out.println(ServiceInitializer.INSTANCE);//Print Address @54d41c2b
      }
}

Update

I printed the classloader for the classes and it turns out for first print statement the classloder was sun.misc.Launcher$AppClassLoader and for the second print statement the classloder was org.powermock.core.classloader.MockClassLoader. How can I solve this?


Solution

  • Well I finally found the work around for this problem. As explained in my question my class was getting loaded by two different class loaders and thus causing problems for me. In order to resolve my issue I used @PowerMockIgnore annotation in order to defer its loading as follows:

    @PowerMockIgnore({"com.mypackage.*"})
    class BaseTest{
          // Stuff goes here
    }
    

    This annotation tells PowerMock to defer the loading of classes with the names supplied to value() to the system classloader. You can read about this annotation from here.