如何防止创建模拟对象以运行静态内容?

时间:2016-11-11 10:08:43

标签: java junit mocking

鉴于此代码:

class Booh {
  final static Booh throwUp = new Booh();
  Booh() { throw new RuntimeException("I didn't see that one coming"); }
}

使用Mokito.mock()进行测试:

@Test 
public void testBooh() {
    Booh booh;
    booh = mock(Booh.class);
  }
}

我最终得到了:

  

java.lang.ExceptionInInitializerError       在java.lang.J9VMInternals.ensureError(J9VMInternals.java:137)       at java.lang.J9VMInternals.recordInitializationFailure(J9VMInternals.java:126)       at sun.reflect.GeneratedSerializationConstructorAccessor12.newInstance(Unknown Source)       at java.lang.reflect.Constructor.newInstance(Constructor.java:436)       at org.objenesis.instantiator.sun.SunReflectionFactoryInstantiator.newInstance(SunReflectionFactoryInstantiator.java:56)       at org.objenesis.ObjenesisBase.newInstance(ObjenesisBase.java:73)       在org.mockito.internal.creation.jmock.ClassImposterizer.createProxy(ClassImposterizer.java:128)       在org.mockito.internal.creation.jmock.ClassImposterizer.imposterise(ClassImposterizer.java:63)       在org.mockito.internal.creation.jmock.ClassImposterizer.imposterise(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)       at my.test.Class.testBooh(my.test.Class.java:162)       ....

引起:java.lang.RuntimeException:我没看到那个人来了 ...

简单的问题:有什么方法可以防止这种异常;不改变生产代码以避免那个静态初始化的东西?

(上面的代码是一个mcve;实际上,事情更复杂,但最终我们的问题是单元测试代码试图模拟一个类......这会导致大量的静态结束初始化;以及一些初始语句在我们的单元测试环境中抛出。)

为了记录:这不是Mokito问题,我使用EasyMock遇到了同样的问题。

1 个答案:

答案 0 :(得分:3)

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

@Test
public void testBooh(@Mocked(stubOutClassInitialization = true) Booh booh) {
    ...
}

(默认情况下,stubOutClassInitializationfalse,因为删除类的静态初始化程序意味着任何static final字段在测试运行结束前将保持未初始化状态,因为仅限JVM每个加载的类执行静态初始化一次。)

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