Замена PowerMock @PrepareForTest программно?

Я использую 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() {
    ...
  }

}

Это отлично работает, но я считаю, что указание аннотации @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() {
    ...
  }

}

Здесь my unit test имеет зависимость от LibraryOne, но не знает, от каких классов LibraryOne зависит, поэтому он не знает, какие классы добавить в аннотацию @PrepareForTest.

Я мог бы сделать SomeUnitTest extend 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);
  }

}

Я думаю, было бы неплохо, если бы PowerMockRunner обработало аннотацию @PrepareForTest несколько иначе: для каждого указанного класса он должен не только добавить этот класс (и его иерархию) в список классов для подготовки к издевательствам, но затем изучите этот класс, чтобы увидеть, есть ли в нем аннотации @PrepareForTest:

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

@PrepareForTest({Foo.class,Bar.class})
public class MockLibraryOne {
  ...
}

}

Итак, в этом аннотация @PrepareForTest на SomeUnitTest найдет MockLibraryOne, а аннотация @PrepareForTest будет таскать в Foo.class и Bar.class.

Поэтому, возможно, написать мой собственный тестовый бегун для замены PowerMockRunner может быть решением.

Или, может быть, есть более простое решение, используя класс PowerMockAgent, например?

edit: Mock Policies может быть одним из решений: https://code.google.com/p/powermock/wiki/MockPolicies

edit: Mock Policies работает с PowerMockRunner, но не (кажется) с PowerMockRule (что я иногда требую из-за проблем загрузчика класса).

Ответы

Ответ 2

Почему вы даже хотите издеваться над статическими методами? Почему бы не обернуть эти статические методы в классе, который вы можете высмеивать с помощью mockito?

class FooWraper {
   void someMethod() {
     Foo.someStaticMethod()
   }
}

а затем вы можете создать макет вашего FooWraper. Нет необходимости использовать Powermock вообще...