这是我的源类-
public class ClassToTest extends AbstractSuperClass<Integer> {
private static final ClassToTest INSTANCE = new ClassToTest(); // (line 1) need to mock this variable
static ClassToTest get() {
return INSTANCE;
}
private ClassToTest() {
super(Integer.class);// (line 2)
}
}
这是我到目前为止测试它的尝试
@RunWith(PowerMockRunner.class)
@PrepareForTest(ClassToTest.class)
public class TestClass {
private ClassToTest testClass;
@Before
public void setUp() {
// each of the below attempts fails at line 1 because of the call to line 2 (annotated above).
// Attempt A.
testClass = WhiteBox.newInstance(ClassToTest.class);
//Attempt B.
testClass = mock(ClassToTest.class);
WhiteBox.setInternalState(ClassToTest.class, "INSTANCE", testClass);
}
@Test
public void dummy() {
// irrelevant
}
}
我试图有效地模拟ClassToTest.INSTANCE
和调用它的私有构造函数。我怎么能这么做呢?
编辑:代码片段/构造函数从AbstractSuperClass
中调用。
public abstract class AbstractSuperClass<V extends Serializable> {
private final CacheClient<V> cache;
private final int seconds;
public AbstractSuperClass(Class<V> valueType) {
cache = new ClientFactory(Config.getAppConfig(), StatisticSet.getGlobalStatistics()).newClient(getCacheType(), valueType);
seconds = Config.getAppConfig().get(getCacheType().getSectionEnum()).getSeconds();
}
p。S:我试着远离处理AbstractSuperClass
的内部,本来希望简单地嘲笑电话。我也愿意接受重构ClassToTest
以避免这种情况的任何想法。
我不明白你想要实现什么,但这是工作在这里:
@PrepareForTest(ClassToTest.class) // required
@RunWith(PowerMockRunner.class) // required
public class ClassToTestTest {
private ClassToTest testClass;
@Before
public void setUp() throws Exception {
this.testClass = Mockito.mock(ClassToTest.class);
final Field instance = ClassToTest.class.getDeclaredField("INSTANCE");
instance.setAccessible(true);
instance.set(null, this.testClass);
}
@Test
public void testGet() throws Exception {
assertSame(this.testClass, ClassToTest.get());
System.out.println(this.testClass);
}
}
输出:Mock for ClassToTest, hashCode: 1083021083
(使用powermock-api-mock版本1.6.2进行测试)
我不相信模拟字段是正确的方法,我甚至不相信这是可能的,因为你不能覆盖字段只有方法可以被覆盖,这实际上是模拟的工作方式。实际上,模拟在某种程度上只是我们覆盖方法的代理。
您应该模仿ClassToTest.get()
而不是下一个:
@RunWith(PowerMockRunner.class)
@PrepareForTest(ClassToTest.class)
public class TestClass {
private ClassToTest testClass;
@Before
public void setUp() {
testClass = PowerMockito.mock(ClassToTest.class);
PowerMockito.mockStatic(ClassToTest.class);
Mockito.when(ClassToTest.get()).thenReturn(testClass);
}
@Test
public void dummy() {
// Here I get the instance of ClassToTest that I mocked in the setUp method
System.out.println(ClassToTest.get());
}
}
您的真正的问题是您通过使用static创建了难以测试的代码。不仅如此:您还创建了一个糟糕的设计。因为您将生产类紧密耦合在一起。一旦到位,以后就很难摆脱这个静态方法。
所以,另一个选择:不是试图通过使用PowerMock来"修复"一个损坏的设计,而是后退一步。你会学到什么是"编写可测试的"代码(例如通过观看这些视频);然后使用纯接口和依赖注入来解决问题。您可以使用EasyMock或Mockito测试所有这些,而无需Powermock!