Powermock 1.6.4 с Javassist 3.24.0-GA создает исключение javassist.CannotCompileException: от javassist.bytecode.BadBytecode

Я использую следующие версии powermock и junit с javaassist. Большинство тестовых случаев работают нормально, за исключением нескольких, написанных для классов, использующих 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

1 ответ

Даже если вы не используете 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.x под Java 11, вы, вероятно, столкнетесь с проблемами.

Кроме того, я бы попробовал обновить Javassist до самой последней версии (3.28.0-GA на момент написания), ИЛИ вы можете попробовать версию javassist, для которой был создан powermock 1.7.4 (3.21.0-GA) ( но это не поможет вам в долгосрочной перспективе).

Если обновление до самой последней версии powermock 1.7.4/javassist по-прежнему дает тот же результат, то, поскольку результатом вашей ошибки является очень низкоуровневое внутреннее сообщение javassist («несогласованная высота стека»), мало что может сделать любой, кто не знаком с его внутренними компонентами. сделать для вас. Следующим вашим шагом, вероятно, будет попытка обновления до PowerMock 2 (для чего также могут потребоваться обновления для Mockito и т. д.).

Вы можете попробовать опубликовать сообщение об ошибке в powermock 1.x или сообщение в их группе google , но... Powermock 2 отсутствует уже несколько лет, и 1.x почти наверняка больше не поддерживается (это не новая версия 1.x версии более 3 лет), поэтому они, вероятно, также скажут вам сначала попробовать PowerMock 2. Если вы все еще получаете ту же ошибку после обновления, возможно, вы нашли ошибку в powermock/javassist, которую стоит исправить, или несовместимость, которую следует задокументировать.

Другие вопросы по тегам