PowerMock PrepareForTest注释导致AmazonSQSClient构造函数出现问题

时间:2013-08-22 15:41:05

标签: java amazon-web-services jenkins powermock

我在使用PrepareForTest注释并创建AmazonSQSClient的新实例时遇到了一些问题。

我正在编写一个Jenkins插件,不幸的是需要模拟FormValidation静态类,以确保在我的插件的字段验证中产生警告和错误消息。但是,在创建AmazonSQSClient的实例时,我会得到org.apache.http.conn.ssl.SSLInitializationException

我把它简化为一个非常简单的例子,这是我的测试文件:

package com.test;

import com.amazonaws.services.sqs.AmazonSQS;
import com.amazonaws.services.sqs.AmazonSQSClient;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;

@RunWith(PowerMockRunner.class)  
public class SQSTest {

    // This is for mimicking the mocking of FormValidation
    private static class Foo {}

    @Test
    @PrepareForTest(Foo.class)
    public void buildTest()
    {
        AmazonSQS sqs = new AmazonSQSClient();
    }
}

运行此代码时出现以下错误:

org.apache.http.conn.ssl.SSLInitializationException: Failure initializing default SSL context
    at org.apache.http.conn.ssl.SSLSocketFactory.createDefaultSSLContext(SSLSocketFactory.java:360)
    at org.apache.http.conn.ssl.SSLSocketFactory.getSocketFactory(SSLSocketFactory.java:175)
    at org.apache.http.impl.conn.SchemeRegistryFactory.createDefault(SchemeRegistryFactory.java:49)
    at org.apache.http.impl.conn.PoolingClientConnectionManager.<init>(PoolingClientConnectionManager.java:93)
    at com.amazonaws.http.ConnectionManagerFactory.createPoolingClientConnManager(ConnectionManagerFactory.java:26)
    at com.amazonaws.http.HttpClientFactory.createHttpClient(HttpClientFactory.java:87)
    at com.amazonaws.http.AmazonHttpClient.<init>(AmazonHttpClient.java:121)
    at com.amazonaws.AmazonWebServiceClient.<init>(AmazonWebServiceClient.java:66)
    at com.amazonaws.services.sqs.AmazonSQSClient.<init>(AmazonSQSClient.java:189)
    at com.amazonaws.services.sqs.AmazonSQSClient.<init>(AmazonSQSClient.java:93)
    at com.test.SQSTest.buildTest(SQSTest.java:19)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at org.junit.internal.runners.TestMethod.invoke(TestMethod.java:68)
    at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl$PowerMockJUnit44MethodRunner.runTestMethod(PowerMockJUnit44RunnerDelegateImpl.java:310)
    at org.junit.internal.runners.MethodRoadie$2.run(MethodRoadie.java:88)
    at org.junit.internal.runners.MethodRoadie.runBeforesThenTestThenAfters(MethodRoadie.java:96)
    at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl$PowerMockJUnit44MethodRunner.executeTest(PowerMockJUnit44RunnerDelegateImpl.java:294)
    at org.powermock.modules.junit4.internal.impl.PowerMockJUnit47RunnerDelegateImpl$PowerMockJUnit47MethodRunner.executeTestInSuper(PowerMockJUnit47RunnerDelegateImpl.java:127)
    at org.powermock.modules.junit4.internal.impl.PowerMockJUnit47RunnerDelegateImpl$PowerMockJUnit47MethodRunner.executeTest(PowerMockJUnit47RunnerDelegateImpl.java:82)
    at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl$PowerMockJUnit44MethodRunner.runBeforesThenTestThenAfters(PowerMockJUnit44RunnerDelegateImpl.java:282)
    at org.junit.internal.runners.MethodRoadie.runTest(MethodRoadie.java:86)
    at org.junit.internal.runners.MethodRoadie.run(MethodRoadie.java:49)
    at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl.invokeTestMethod(PowerMockJUnit44RunnerDelegateImpl.java:207)
    at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl.runMethods(PowerMockJUnit44RunnerDelegateImpl.java:146)
    at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl$1.run(PowerMockJUnit44RunnerDelegateImpl.java:120)
    at org.junit.internal.runners.ClassRoadie.runUnprotected(ClassRoadie.java:33)
    at org.junit.internal.runners.ClassRoadie.runProtected(ClassRoadie.java:45)
    at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl.run(PowerMockJUnit44RunnerDelegateImpl.java:118)
    at org.powermock.modules.junit4.common.internal.impl.JUnit4TestSuiteChunkerImpl.run(JUnit4TestSuiteChunkerImpl.java:101)
    at org.powermock.modules.junit4.common.internal.impl.AbstractCommonPowerMockRunner.run(AbstractCommonPowerMockRunner.java:53)
    at org.powermock.modules.junit4.PowerMockRunner.run(PowerMockRunner.java:53)
    at org.junit.runner.JUnitCore.run(JUnitCore.java:160)
    at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:77)
    at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:195)
    at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:63)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:120)
Caused by: java.security.NoSuchAlgorithmException: class configured for KeyManagerFactory: sun.security.ssl.KeyManagerFactoryImpl$SunX509 not a KeyManagerFactory
    at sun.security.jca.GetInstance.checkSuperClass(GetInstance.java:258)
    at sun.security.jca.GetInstance.getInstance(GetInstance.java:237)
    at sun.security.jca.GetInstance.getInstance(GetInstance.java:164)
    at javax.net.ssl.KeyManagerFactory.getInstance(KeyManagerFactory.java:138)
    at org.apache.http.conn.ssl.SSLSocketFactory.createSSLContext(SSLSocketFactory.java:223)
    at org.apache.http.conn.ssl.SSLSocketFactory.createDefaultSSLContext(SSLSocketFactory.java:358)
    ... 42 more

为了帮助任何想要快速构建和运行的人,请访问我的pom.xml文件:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.test</groupId>
    <artifactId>test.sqs</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>hpi</packaging>



    <properties>
        <!--
          explicitly specifying the latest version here because one we get from the parent POM
          tends to lag behind a bit
        -->
        <maven-hpi-plugin.version>1.96</maven-hpi-plugin.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>com.amazonaws</groupId>
            <artifactId>aws-java-sdk</artifactId>
            <version>1.5.4</version>
        </dependency>

        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.11</version>
        </dependency>

        <dependency>
            <groupId>org.mockito</groupId>
            <artifactId>mockito-all</artifactId>
            <version>1.9.5</version>
        </dependency>

        <dependency>
            <groupId>org.powermock</groupId>
            <artifactId>powermock-api-mockito</artifactId>
            <version>1.5.1</version>
        </dependency>

        <dependency>
            <groupId>org.powermock</groupId>
            <artifactId>powermock-module-junit4</artifactId>
            <version>1.5.1</version>
        </dependency>

    </dependencies>
</project>

当从方法中删除注释@PrepareForTest(Foo.class)时,测试运行正常。

我想知道是否有人可以解释为什么会发生这种情况,是否有解决方法或避免嘲笑FormValidation类?

感谢。

2 个答案:

答案 0 :(得分:11)

尝试将@PowerMockIgnore("org.apache.http.conn.ssl.*")注释添加到您的班级

答案 1 :(得分:3)

正如@Natalie已经提到的,您可以使用@PowerMockIgnore()注释。也许您需要忽略包javax.net.ssl.*和/或javax.crypto.*

@PowerMockIgnore({"org.apache.http.conn.ssl.*", "javax.net.ssl.*" , "javax.crypto.*"})

您可以在这里获得一些背景信息:

https://groups.google.com/forum/#!topic/powermock/v4nreP2AnOQ

  

这很可能是因为SSLContext是由引导类加载器加载的,而PowerMock不能对这些类进行字节代码操作。您必须使用此方法来模拟该方法。     / Johan Haleby