我正在将Junit 4.12与PowerMock 1.6和Mockito一起使用。我还使用了here所述的PowerMockRule库。我正在尝试对所有测试用例执行一次初始化代码,如this SO Thread中所述。它仅执行一次初始化代码,但是,如果我在测试方法中执行ServiceInitializer.INSTANCE,它将返回新对象。我无法理解这种行为。有谁知道为什么会这样吗?如果我在没有PowerMockRule库的情况下执行我的代码,并在PowerMockRunner中运行测试,那么它可以正常工作,但在这种情况下,我的ClassRule没有得到执行。

    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
      }
}


更新资料

我为这些类打印了类加载器,结果显示,对于第一个打印语句,classloder为sun.misc.Launcher$AppClassLoader,对于第二个打印语句,classloder为org.powermock.core.classloader.MockClassLoader。我该如何解决?

最佳答案

您没有单身人士。您有一个静态的INSTANCE变量。请记住,您拥有的每个类加载器都可以存在其中之一。

而是像这样制作一个ServiceInitializer枚举

public enum ServiceInitializer {
  INSTANCE;

  // rest of class goes here
}


并依靠JVM的语言契约来确保单例。

或者,更好的是,编写代码来处理可能存在多个ServiceInitializer的情况,但是恰好您的程序仅使用一个实例。这是理想的选择,允许您在实际的ServiceInitializer和模拟对象之间进行切换。

10-07 22:45