以编程方式替换PowerMock的@PrepareForTest?

Joh*_*zen 23 junit unit-testing powermock

我正在使用PowerMock在junit测试中模拟静态方法,通常如下所示:

@RunWith(PowerMockRunner.class)
@PrepareForTest({Foo.class,Bar.class})
public class SomeUnitTest {

  @Before
  public void setUpTest() {
    setUpFoo();
    setUpBar();
  }

  private void setUpFoo() {
    mockStatic(Foo.class);
    when(Foo.someStaticMethod()).thenReturn(1);
  }

  private void setUpBar() {
    mockStatic(Bar.class);
    when(Bar.someStaticMethod()).thenReturn(2);
  }

  @Test
  public void someTestCase() {
    ...
  }

}
Run Code Online (Sandbox Code Playgroud)

这工作正常,但我发现指定@PrepareForTest注释阻止我使我的测试API灵活.

我想做的是如下:

public class MockLibraryOne {

  public static void setUpLibraryOne() {
    setUpFoo();
    setUpBar();
  }

  private static void setUpFoo() {
    mockStatic(Foo.class);
    when(Foo.someStaticMethod()).thenReturn(1);
  }

  private static void setUpBar() {
    mockStatic(Bar.class);
    when(Bar.someStaticMethod()).thenReturn(2);
  }

}

@RunWith(PowerMockRunner.class)
public class SomeUnitTest {

  @Before
  public void setUpTest() {
    MockLibraryOne.setUpLibraryOne();
  }

  @Test
  public void someTestCase() {
    ...
  }

}
Run Code Online (Sandbox Code Playgroud)

这里我的单元测试依赖于LibraryOne,但它不知道哪些类LibraryOne依赖,所以它不知道要添加到@PrepareForTest注释的类.

我可以进行SomeUnitTest扩展MockLibraryOne并将@PrepareForTest注释添加到MockLibraryOne类中,但是我将依赖MockLibraryOne于其他单元测试,因此继承不是一般解决方案.

有没有一种方法可以在PowerMock下以编程方式准备一个类进行测试,而不是使用@PrepareForTest注释?例如,类似以下内容:

public class MockLibraryOne {

  public static void setUpLibraryOne() {
    setUpFoo();
    setUpBar();
  }

  private static void setUpFoo() {
    prepareForTest(Foo.class);
    mockStatic(Foo.class);
    when(Foo.someStaticMethod()).thenReturn(1);
  }

  private static void setUpBar() {
    prepareForTest(Bar.class);
    mockStatic(Bar.class);
    when(Bar.someStaticMethod()).thenReturn(2);
  }

}
Run Code Online (Sandbox Code Playgroud)

我想如果PowerMockRunner处理@PrepareForTest注释有点不同会很好:对于每个指定的类,它不仅应该将该类(及其层次结构)添加到类列表中以准备模拟,而是检查该类以查看它是否还有任何@PrepareForTest注释:

@RunWith(PowerMockRunner.class)
@PrepareForTest({MockLibraryOne.class})
public class SomeUnitTest {
  ...
}

@PrepareForTest({Foo.class,Bar.class})
public class MockLibraryOne {
  ...
}
Run Code Online (Sandbox Code Playgroud)

}

所以在这个@PrepareForTest注释上SomeUnitTest会发现MockLibraryOne,和@PrepareForTest注释会有拖动Foo.classBar.class为好.

因此,编写我自己的测试运行器来替换PowerMockRunner可能是一个解决方案.

或者也许有一个更简单的解决方案,PowerMockAgent例如使用类?

编辑:模拟策略可能是一个解决方案:https://code.google.com/p/powermock/wiki/MockPolicies

编辑:模拟策略与PowerMockRunner(但似乎)一起使用PowerMockRule(由于类加载器问题,我有时需要).

Joh*_*han 0

也许您正在寻找模拟政策