我在javaassist中使用以下版本的powermock和junit。大多数测试用例都工作得很好,除了少数是为使用CloseableHttpClient的类编写的。我尝试了powermock + javaassist的不同组合,但似乎没有任何作用。我的项目是遗留的,因此没有使用maven。
javassist-3.24.0-GA
powermock-api-mockito-1.6.2
powermock-mockito-release-full-1.6.4-full
powermock-module-junit4-1.7.4
powermock-module-testng-1.6.6
junit-4.12.jar
——代码
import static org.mockito.Matchers.anyObject;
import static org.mockito.Matchers.anyString;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.rmi.registry.Registry;
import javax.xml.parsers.ParserConfigurationException;
import org.apache.http.HttpEntity;
import org.apache.http.StatusLine;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.config.RequestConfig.Builder;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.conn.socket.ConnectionSocketFactory;
import org.apache.http.conn.socket.PlainConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.junit.runner.RunWith;
import org.mockito.Matchers;
import org.mockito.Mockito;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PowerMockIgnore;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.core.classloader.annotations.SuppressStaticInitializationFor;
import org.powermock.modules.junit4.PowerMockRunner;
import org.powermock.modules.testng.PowerMockTestCase;
import org.testng.Assert;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
import org.w3c.dom.Document;
import com.yantra.yfc.log.YFCLogCategory;
import com.yantra.yfs.core.YFSSystem;
import com.yantra.yfs.japi.YFSEnvironment;
import com.yantra.yfs.japi.YFSUserExitException;
@RunWith(PowerMockRunner.class)
@PrepareForTest({HttpClientBuilder.class, PoolingHttpClientConnectionManager.class,Registry.class})
@PowerMockIgnore({"javax.management.*", "org.apache.http.conn.ssl.*", "com.amazonaws.*", "javax.net.ssl.*","com.sun.*"})
@SuppressStaticInitializationFor({ "com.yantra.yfs.core.YFSSystem" , "org.apache.http.client.config.RequestConfig",
"org.apache.http.conn.ssl.SSLConnectionSocketFactory", "org.apache.http.impl.client.HttpClients","org.apache.http.impl.client.HttpClientBuilder","org.apache.http.config.Registry","org.apache.http.config.RegistryBuilder","org.apache.http.HttpEntity"})
public class ConfirmRefundDistributionUETest extends PowerMockTestCase{
private ConfirmRefundDistributionUE confirmRefundDistributionUE;
private YFSEnvironment yfsEnvironment;
private YFCLogCategory yfc;
ConfirmRefundDistributionUEYIFAPI mockYIFApi;
CloseableHttpClient client ;
CloseableHttpResponse response;
HttpClientBuilder httpClientBuilder ;
RequestConfig defaultRequestConfig;
Builder customBuilder ;
PoolingHttpClientConnectionManager poolManager;
Registry rgt ;
org.apache.http.config.Registry registry;
RegistryBuilder rb ;
StatusLine sl;
HttpEntity he;
@BeforeMethod
public void beforeMethod() throws Exception {
PowerMockito.mockStatic(SSLConnectionSocketFactory.class);
PowerMockito.mockStatic(RequestConfig.class);
PowerMockito.mockStatic(HttpClients.class);
PowerMockito.mockStatic(RegistryBuilder.class);
PowerMockito.mockStatic(PlainConnectionSocketFactory.class);
PowerMockito.mockStatic(HttpClientBuilder.class);
client = PowerMockito.mock(CloseableHttpClient.class);
httpClientBuilder = PowerMockito.mock(HttpClientBuilder.class);
PowerMockito.when(HttpClients.custom()).thenReturn(httpClientBuilder);
Mockito.when(httpClientBuilder.setConnectionManager(anyObject())).thenReturn(httpClientBuilder);
PowerMockito.when(httpClientBuilder.setDefaultRequestConfig(Matchers.anyObject())).thenReturn(httpClientBuilder);
PowerMockito.when(httpClientBuilder.setProxy(Matchers.anyObject())).thenReturn(httpClientBuilder);
PowerMockito.when(httpClientBuilder.build()).thenReturn(client);
PowerMockito.when(client.execute(anyObject())).thenReturn(response);
PowerMockito.when(response.getStatusLine()).thenReturn(sl);
}
@Test
public void confirmRefundDistribution() throws ParserConfigurationException, SAXException, IOException, YFSUserExitException {
// get the input.
Document docUEInput = getDocument("InputUE");
// invoke method to be tested.
Document docActualUEOutput = confirmRefundDistributionUE.confirmRefundDistribution(yfsEnvironment, docUEInput);
// Assert Output
Document docExpectedUEOutput = getDocument("OutputUE");
Assert.assertEquals(XMLUtil.getXMLString(docExpectedUEOutput), XMLUtil.getXMLString(docActualUEOutput));
}
}
堆栈跟踪,
javassist.CannotCompileException: by javassist.bytecode.BadBytecode: build ()Lorg/apache/http/impl/client/CloseableHttpClient; in org.apache.http.impl.client.HttpClientBuilder: inconsistent stack height 21
at javassist.CtBehavior.insertBefore(CtBehavior.java:809)
at javassist.CtBehavior.insertBefore(CtBehavior.java:766)
at org.powermock.core.transformers.impl.MainMockTransformer.modifyMethod(MainMockTransformer.java:197)
at org.powermock.core.transformers.impl.MainMockTransformer.allowMockingOfStaticAndFinalAndNativeMethods(MainMockTransformer.java:133)
at org.powermock.core.transformers.impl.MainMockTransformer.transform(MainMockTransformer.java:65)
at org.powermock.core.classloader.MockClassLoader.loadMockClass(MockClassLoader.java:252)
at org.powermock.core.classloader.MockClassLoader.loadModifiedClass(MockClassLoader.java:180)
at org.powermock.core.classloader.DeferSupportingClassLoader.loadClass(DeferSupportingClassLoader.java:70)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:344)
at sun.reflect.generics.factory.CoreReflectionFactory.makeNamedType(CoreReflectionFactory.java:114)
at sun.reflect.generics.visitor.Reifier.visitClassTypeSignature(Reifier.java:125)
at sun.reflect.generics.tree.ClassTypeSignature.accept(ClassTypeSignature.java:49)
at sun.reflect.annotation.AnnotationParser.parseSig(AnnotationParser.java:439)
at sun.reflect.annotation.AnnotationParser.parseClassValue(AnnotationParser.java:420)
at sun.reflect.annotation.AnnotationParser.parseClassArray(AnnotationParser.java:724)
at sun.reflect.annotation.AnnotationParser.parseArray(AnnotationParser.java:531)
at sun.reflect.annotation.AnnotationParser.parseMemberValue(AnnotationParser.java:355)
at sun.reflect.annotation.AnnotationParser.parseAnnotation2(AnnotationParser.java:286)
at sun.reflect.annotation.AnnotationParser.parseAnnotations2(AnnotationParser.java:120)
at sun.reflect.annotation.AnnotationParser.parseAnnotations(AnnotationParser.java:72)
at java.lang.Class.createAnnotationData(Class.java:3513)
at java.lang.Class.annotationData(Class.java:3502)
at java.lang.Class.getAnnotation(Class.java:3407)
at org.testng.internal.annotations.JDK15AnnotationFinder.findAnnotationInSuperClasses(JDK15AnnotationFinder.java:84)
at org.testng.internal.annotations.JDK15AnnotationFinder.findAnnotation(JDK15AnnotationFinder.java:150)
at org.testng.internal.annotations.AnnotationHelper.findTest(AnnotationHelper.java:31)
at org.testng.internal.MethodHelper.isEnabled(MethodHelper.java:189)
at org.testng.internal.Invoker.invokeConfigurations(Invoker.java:184)
at org.testng.internal.Invoker.invokeMethod(Invoker.java:653)
at org.testng.internal.Invoker.invokeTestMethod(Invoker.java:901)
at org.testng.internal.Invoker.invokeTestMethods(Invoker.java:1231)
at org.testng.internal.TestMethodWorker.invokeTestMethods(TestMethodWorker.java:127)
at org.testng.internal.TestMethodWorker.run(TestMethodWorker.java:111)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)
Caused by: javassist.bytecode.BadBytecode: build ()Lorg/apache/http/impl/client/CloseableHttpClient; in org.apache.http.impl.client.HttpClientBuilder: inconsistent stack height 21
at javassist.bytecode.stackmap.MapMaker.make(MapMaker.java:119)
at javassist.bytecode.MethodInfo.rebuildStackMap(MethodInfo.java:458)
at javassist.bytecode.MethodInfo.rebuildStackMapIf6(MethodInfo.java:440)
at javassist.CtBehavior.insertBefore(CtBehavior.java:800)
... 37 more
Caused by: javassist.bytecode.BadBytecode: inconsistent stack height 21
at javassist.bytecode.stackmap.Tracer.doOpcode(Tracer.java:81)
at javassist.bytecode.stackmap.MapMaker.make(MapMaker.java:195)
at javassist.bytecode.stackmap.MapMaker.make(MapMaker.java:207)
at javassist.bytecode.stackmap.MapMaker.make(MapMaker.java:172)
at javassist.bytecode.stackmap.MapMaker.make(MapMaker.java:116)
... 40 more
Caused by: java.lang.ArrayIndexOutOfBoundsException: 21
at javassist.bytecode.stackmap.Tracer.doASTORE(Tracer.java:422)
at javassist.bytecode.stackmap.Tracer.doOpcode54_95(Tracer.java:299)
at javassist.bytecode.stackmap.Tracer.doOpcode(Tracer.java:75)
... 44 more
即使您不使用Maven,您也应该尝试使用一致版本的依赖项。你有1.6.2、1.6.4、1.6.6、1.7.4……您应该为所有powermock库使用相同的版本。1的最后一个版本。x = 1.7.4,所以我建议从这里开始。把它们混在一起是自找麻烦——对junit4模块的更改可能依赖于核心版本中较低级别的更改。
你没有指定你使用哪个java版本,也不是httpclient,也不是Mockito,所以我不得不假设那里没有兼容性问题。例如,如果您尝试使用Powermock 1。
除此之外,我会尝试更新到最新版本的Javassist(在撰写本文时为3.28.0-GA),或者您可以尝试powermock 1.7.4构建的Javassist版本(3.21.0-GA)(但这不会对您有长期帮助)。
如果更新到最新的powermock 1.7.4/javassist仍然给出相同的结果,那么由于您的错误结果是非常低级的内部javassist消息("不一致的堆栈高度"),因此不熟悉其内部的人几乎无法为您做什么。您的下一步可能是尝试更新到PowerMock 2(这可能还需要更新到Mockito等)。
您可以尝试发布针对powermock 1的错误。或者在他们的谷歌群里发消息,但是……Powermock 2已经发布好几年了。几乎可以肯定的是,X已经不再被支持了(没有一个新的版本)。x版本使用了3年多),所以他们可能还会告诉您先尝试PowerMock 2。如果在升级后仍然得到相同的错误,那么您可能发现了powermock/javassist中值得修复的错误,或者应该记录的不兼容性。