我想编写一些使用Junit 4.12,Mockito 1.9.5和PowerMock 1.6.1的单元测试。该类具有@mock注释的一些字段,以及@InjectMocks注释的一些字段。用@InjectMocks注释的属性在某个时候达到了一个包含某些静态方法调用的父构造器,应使用PowerMock对其进行模拟。问题是第一个测试无缝起作用,而第二个测试似乎根本没有模拟静态方法。
@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();
}
}
如前所述,第一个测试通过,staticclass.staticmethod((被PowerMock所预期的。第二个测试不会通过,当调用某些hotershod的值时,它会在线上抛出NullPoInterException(因为value = null,因为staticclass.staticmethod不再被PowerMock嘲笑(。
如(使用PowerMock在每次测试后重置(PowerMock在每个测试之前重置模拟。
由于某种原因,它第一次起作用 - 存在该问题的未解决的错误报告(https://github.com/powermock/powermock/issues/398(。
它的设计可以说是不好的,但是做您想做的事情的一种方法是:
而不是依靠注释手动设置模拟。
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;
}
首选的方法是使用SomeOtherClass
的构造函数提供attribute
您必须从外部设置值。
如果无法访问attribute
实例,则可能被迫使用反射。
清洁剂的方法是重构SomeOtherClass
的构造函数,以不使用内部静态方法。而是将SomeConcreteClass
作为参数传递给构造函数是要走的方式。
有些人甚至说您不应该在构造函数内有任何逻辑。