Quiero escribir algunas pruebas unitarias, que el uso Junit 4.12, Mockito 1.9.5 y 1.6.1 PowerMock. La clase tiene algunos campos con anotada @Mock, así como algunos campos con anotada @InjectMocks. El atributo que se anota con @InjectMocks alcances en algún momento un constructor matriz que contiene algún método invocación estática, que debe ser burlado con PowerMock. El problema es la primera prueba funciona a la perfección, mientras que la segunda prueba no parece burlarse de los métodos estáticos en absoluto.
@RunWith(PowerMockRunner.class)
@PrepareForTest({ StaticClass.class })
public class TestClass {
@Mock
private SomeClass attribute1;
@InjectMocks
private SomeOtherClass attribute2;
@BeforeClass
public static void setUp() {
PowerMockito.mockStatic(StaticClass.class);
when(StaticClass.staticMethod(any(), any()).thenReturn(new SomeConcreteClass());
}
@Test
public void test1() {
assertEquals(attribute2.method1(), value1);
}
@Test
public void test2() {
assertEquals(attribute2.method2(), value2);
}
}
public class SomeOtherClass {
private SomeClass attribute;
public SomeOtherClass() {
SomeConcreteClass value = StaticClass.staticMethod(argument1, argument2);
value.someOtherMethod();
}
}
Como se mencionó antes, la primera prueba pasa y la StaticClass.staticMethod () puede ser burlado como se esperaba por PowerMock. La segunda prueba no pasa y se lanza una NullPointerException en línea cuando someOtherMethod se llama en el valor (porque el valor = null, como el StaticClass.staticMethod no fue burlado más por PowerMock).
Como se explica en ( restablece comportamiento burlando de después de cada prueba con PowerMock ) Powermock restablece los burla antes de cada prueba.
Por alguna razón, funciona la primera vez - existe un informe de error sin solución por esa cuestión ( https://github.com/powermock/powermock/issues/398 ).
Su posiblemente mal diseño, sino una manera de hacer lo que quiere es la siguiente:
En lugar de confiar en el conjunto de anotaciones a los simulacros de forma manual.
private SomeClass attribute;
private SomeOtherClass testClass;
@Before
public void setUp() {
PowerMockito.mockStatic(StaticClass.class);
Mockito.when(StaticClass.staticMethod(anyString())).thenReturn(new SomeConcreteClass());
attribute = Mockito.mock(SomeClass.class);
testClass = new SomeOtherClass();
// assign mock manually
testClass.attribute = attribute;
}
La forma preferida sería para abastecer a la attribute
utilización del constructor de SomeOtherClass
,
sin embargo, ya que parece que utilizar un constructor vacío tendrá que establecer el valor desde el exterior.
Si la attribute
instancia no es accesible que podría verse obligado a utilizar reflexiones.
La forma más limpia sería refactorizar el constructor de ustedes SomeOtherClass
para no utilizar un método estático en el interior. En lugar de pasar SomeConcreteClass
como un parámetro para el constructor es el camino a seguir.
Algunas personas incluso decir que no debe tener ninguna lógica en el interior de un constructor.