unit testing - method - ¿Reemplazando programáticamente el @PrepareForTest de PowerMock?
powermock static method (2)
Estoy usando PowerMock para simular métodos estáticos en las pruebas de junit, que normalmente se realiza de la siguiente manera:
@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() {
...
}
}
Esto funciona bien, pero me @PrepareForTest
que la especificación de la anotación @PrepareForTest
impide que mi API de pruebas sea flexible.
Lo que me gustaría hacer es algo como lo siguiente:
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() {
...
}
}
Aquí mi prueba de unidad depende de LibraryOne
, pero no sabe de qué clases depende LibraryOne
, por lo que no sabe qué clases agregar a la anotación @PrepareForTest
.
Podría hacer que SomeUnitTest
extienda MockLibraryOne
y agregue la anotación @PrepareForTest
a la clase MockLibraryOne
, pero tendré dependencias en más que solo MockLibraryOne
en otras pruebas de unidad, por lo que la herencia no es una solución general.
¿Hay alguna forma de preparar mediante programación una clase para realizar pruebas en PowerMock, en lugar de usar la anotación @PrepareForTest
? Por ejemplo, algo como lo siguiente:
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);
}
}
Supongo que sería bueno si PowerMockRunner
procesara la anotación @PrepareForTest
un poco diferente: para cada clase especificada, no solo debería agregar esa clase (y su jerarquía) a la lista de clases para prepararse para el simulacro, sino que luego examinar esa clase para ver si tiene alguna anotación @PrepareForTest
también:
@RunWith(PowerMockRunner.class)
@PrepareForTest({MockLibraryOne.class})
public class SomeUnitTest {
...
}
@PrepareForTest({Foo.class,Bar.class})
public class MockLibraryOne {
...
}
}
Entonces, en esta anotación de SomeUnitTest
en SomeUnitTest
se encontraría MockLibraryOne
, y la anotación de @PrepareForTest
se arrastraría también en Foo.class
y Bar.class
también.
Entonces tal vez escribir mi propio corredor de prueba para reemplazar PowerMockRunner
puede ser una solución.
¿O tal vez hay una solución más simple, usando la clase PowerMockAgent
, por ejemplo?
edición: las Políticas simuladas pueden ser una solución: https://code.google.com/p/powermock/wiki/MockPolicies
edición: Políticas simuladas funciona con PowerMockRunner
pero no (parece) con PowerMockRule
(que a veces necesito debido a problemas con el cargador de clases).
¿Por qué incluso quieres burlarte de los métodos estáticos? ¿Por qué no envolver esos métodos estáticos en una clase de la que puedes burlarte con mockito?
class FooWraper {
void someMethod() {
Foo.someStaticMethod()
}
}
y luego puedes crear un simulacro de tu FooWraper. No hay necesidad de usar Powermock en absoluto ...
Tal vez usted está buscando una política simulada ?