Java 如何防止创建模拟对象来运行静态初始化?

Java 如何防止创建模拟对象来运行静态初始化?,java,junit,mocking,Java,Junit,Mocking,鉴于此代码: class Booh { final static Booh throwUp = new Booh(); Booh() { throw new RuntimeException("I didn't see that one coming"); } } 以及使用Mokito.mock()的测试: 我的结局是: java.lang.ExceptionInInitializeError 在java.lang.J9VMInternals.ensureError(J9VMInter

鉴于此代码:

class Booh {
  final static Booh throwUp = new Booh();
  Booh() { throw new RuntimeException("I didn't see that one coming"); }
}
以及使用Mokito.mock()的测试:

我的结局是:

java.lang.ExceptionInInitializeError 在java.lang.J9VMInternals.ensureError(J9VMInternals.java:137) 在java.lang.J9VMInternals.recordInitializationFailure(J9VMInternals.java:126)中 位于sun.reflect.GeneratedSerializationConstructorAccessor12.newInstance(未知源) 位于java.lang.reflect.Constructor.newInstance(Constructor.java:436) 位于org.objenesis.instantiator.sun.SunReflectionFactoryInstantiator.newInstance(SunReflectionFactoryInstantiator.java:56) 位于org.objenesis.ObjenesisBase.newInstance(ObjenesisBase.java:73) 位于org.mockito.internal.creation.jmock.ClassImposterizer.createProxy(ClassImposterizer.java:128) 位于org.mockito.internal.creation.jmock.ClassImposterizer.importerise(ClassImposterizer.java:63) 位于org.mockito.internal.creation.jmock.ClassImposterizer.importise(ClassImposterizer.java:56) 位于org.mockito.internal.creation.CglibMockMaker.createMock(CglibMockMaker.java:23) 位于org.mockito.internal.util.MockUtil.createMock(MockUtil.java:26) 位于org.mockito.internal.MockitoCore.mock(MockitoCore.java:51) 位于org.mockito.mockito.mock(mockito.java:1243) 位于org.mockito.mockito.mock(mockito.java:1120) 在my.test.Class.testBooh(my.test.Class.java:162)

原因:java.lang.RuntimeException:我没看到会发生这样的情况

简单的问题:我有什么方法可以防止这种例外;不改变生产代码来避免静态初始化

(上面的代码是一个mcve;事实上,事情更加复杂,但最终我们的问题是单元测试代码试图模拟一个类……这导致大量的静态期末考试被初始化;一些init语句出现在我们的单元测试环境中)


作为记录:这不是一个Mokito问题,例如,我使用EasyMock遇到了相同的问题

一种解决方案是使用JMockit模拟类:

@Test
public void testBooh(@Mocked(stubOutClassInitialization = true) Booh booh) {
    ...
}
(默认情况下,
stubOutClassInitialization
false
,因为去掉类的静态初始值设定项意味着任何
static final
字段都将保持未初始化状态,直到测试运行结束,因为JVM只对每个加载的类执行一次静态初始化。)


除此之外,您还必须使用其他字节码操作工具(AspectJ、JBoss AOP、JBoss Byteman)或修复在静态初始化过程中失败的实际生产类。

查看我的更新-即使在模拟步骤之前声明Booh,也会为mock()引发异常电话线。我不确定我是否理解这个问题:你根本不能加载那个类,不管有没有嘲笑。那么如何在生产代码中使用它呢?或者,你是在问如何阻止你嘲笑它不会导致类被加载。尝试
System.out.println(Booh.throwUp)
mock
行之前。显然在PowerMock中有一个注释
@SuppressStaticInitializationFor(classname)
。也许这能帮你?另请参阅并回答。@QBrute可能会有所帮助,但我们这里有一个严格的“无powermock”政策。
@Test
public void testBooh(@Mocked(stubOutClassInitialization = true) Booh booh) {
    ...
}