note
note copied to clipboard
TestNG + PowerMock + Mockito 测试 static 方法遇到的问题
下面的问题搞了我两天,有时候一个小问题找不到原因,就会心烦意乱的,再此记录一下,如有遇到,可以少走弯路。
错误一
错误堆栈
java.lang.RuntimeException: java.lang.ExceptionInInitializerError
at org.testng.internal.MethodInvocationHelper.invokeDataProvider(MethodInvocationHelper.java:161)
at org.testng.internal.Parameters.handleParameters(Parameters.java:429)
at org.testng.internal.Invoker.handleParameters(Invoker.java:1383)
........
at org.testng.remote.RemoteTestNG.initAndRun(RemoteTestNG.java:204)
at org.testng.remote.RemoteTestNG.main(RemoteTestNG.java:175)
Caused by: java.lang.ExceptionInInitializerError
at org.mockito.internal.exceptions.stacktrace.ConditionalStackTraceFilter.<init>(ConditionalStackTraceFilter.java:17)
at org.mockito.exceptions.base.MockitoException.filterStackTrace(MockitoException.java:30)
........
at java.lang.reflect.Method.invoke(Unknown Source)
at org.testng.internal.MethodInvocationHelper.invokeMethod(MethodInvocationHelper.java:84)
at org.testng.internal.MethodInvocationHelper.invokeDataProvider(MethodInvocationHelper.java:135)
... 20 more
Caused by: java.lang.NullPointerException
at org.mockito.internal.exceptions.stacktrace.StackTraceFilter.<clinit>(StackTraceFilter.java:21)
... 50 more
注:由于堆栈信息太多,当中省去了一下代码。
解决方法:
测试的类加上继承:extends PowerMockTestCase
错误二:
错误堆栈
java.lang.ExceptionInInitializerError
at org.objenesis.instantiator.sun.SunReflectionFactoryInstantiator.newInstance(SunReflectionFactoryInstantiator.java:40)
at org.objenesis.ObjenesisBase.newInstance(ObjenesisBase.java:59)
at org.mockito.internal.creation.jmock.ClassImposterizer.createProxy(ClassImposterizer.java:128)
at org.mockito.internal.creation.jmock.ClassImposterizer.imposterise(ClassImposterizer.java:63)
at org.powermock.api.mockito.internal.mockcreation.MockCreator.createMethodInvocationControl(MockCreator.java:111)
at org.powermock.api.mockito.internal.mockcreation.MockCreator.mock(MockCreator.java:60)
at org.powermock.api.mockito.PowerMockito.mockStatic(PowerMockito.java:70)
at com.asp.rc.service.LockSysApiServiceTest.testLockConnect(LockSysApiServiceTest.java:42)
Caused by: org.apache.http.conn.ssl.SSLInitializationException: class configured for SSLContext: sun.security.ssl.SSLContextImpl$TLS10Context not a SSLContext
at org.apache.http.conn.ssl.SSLContexts.createDefault(SSLContexts.java:58)
at org.apache.http.conn.ssl.SSLConnectionSocketFactory.getSocketFactory(SSLConnectionSocketFactory.java:140)
at org.apache.http.impl.conn.PoolingHttpClientConnectionManager.getDefaultRegistry(PoolingHttpClientConnectionManager.java:96)
at org.apache.http.impl.conn.PoolingHttpClientConnectionManager.<init>(PoolingHttpClientConnectionManager.java:103)
at com.asp.util.HttpClientUtil.<clinit>(HttpClientUtil.java:50)
... 8 more
Caused by: java.security.NoSuchAlgorithmException: class configured for SSLContext: sun.security.ssl.SSLContextImpl$TLS10Context not a SSLContext
at org.apache.http.conn.ssl.SSLContexts.createDefault(SSLContexts.java:54)
... 12 more
原因分析
这是因为被 PowerMockito.mockStatic 的类里面有 static 的静态初始方法,而这个方法本身是对HttpClient的初始化:
connManager = new PoolingHttpClientConnectionManager();
connManager.setMaxTotal(200);
connManager.setDefaultMaxPerRoute(20);
httpclient = HttpClients.custom().setConnectionManager(connManager).build();
问题就在这儿,这几行代码会创建示例,这应该是由于和 PowerMock 被替换掉的 .class 信息产生冲突,导致创建不成功。
解决办法
去除被 PowerMockito.mockStatic 类中的可能会影响到的静态初始方法 static {}。
问题二 里如果注释源代码,需要修改代码,更重要的会导致相关的功能无法使用。
下面给出最根本的解决办法,是在 PowerMock 时,忽略SSL 相关的类,如下所示:
@PowerMockIgnore("javax.net.ssl.*")
这样,可以不用注释原代码,并且忽略掉错误。