Yhzhtk / note

知识代码笔记
https://github.com/Yhzhtk/note/issues
MIT License
108 stars 11 forks source link

TestNG + PowerMock + Mockito 测试 static 方法遇到的问题 #28

Open Yhzhtk opened 9 years ago

Yhzhtk commented 9 years ago

下面的问题搞了我两天,有时候一个小问题找不到原因,就会心烦意乱的,再此记录一下,如有遇到,可以少走弯路。

错误一

错误堆栈

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 {}。

Yhzhtk commented 9 years ago

问题二 里如果注释源代码,需要修改代码,更重要的会导致相关的功能无法使用。

下面给出最根本的解决办法,是在 PowerMock 时,忽略SSL 相关的类,如下所示:

@PowerMockIgnore("javax.net.ssl.*")

这样,可以不用注释原代码,并且忽略掉错误。