2014-12-08 153 views
4

我想通过模仿KeyStore和KeyStore.getInstance(KEYSTORE_TYPE)来覆盖KeyStoreException块。但是当我嘲笑KeyStore时,我得到了NoSuchAlgorithmException。你能帮我解决一些例外情况吗?模拟KeyStore的测试KeyStoreException

我已经通过了How to cover block catch by JUnit with NoSuchAlgorithmException and KeyStoreException,这不涉及KeyStoreException

任何想法/解决方案帮助吗?

我的代码

package test; 

import java.io.IOException; 
import java.io.InputStream; 
import java.security.KeyManagementException; 
import java.security.KeyStore; 
import java.security.KeyStoreException; 
import java.security.NoSuchAlgorithmException; 
import java.security.SecureRandom; 
import java.security.UnrecoverableKeyException; 
import java.security.cert.CertificateException; 

import javax.net.ssl.KeyManager; 
import javax.net.ssl.KeyManagerFactory; 
import javax.net.ssl.SSLContext; 
import javax.net.ssl.SSLSocketFactory; 

import org.apache.commons.io.IOUtils; 
import org.slf4j.Logger; 
import org.slf4j.LoggerFactory; 

public class MyClass { 

    private static final Logger LOG = LoggerFactory.getLogger(MyClass.class); 

    private static final String KEYSTORE_TYPE = "PKCS12"; 
    private static final String SSL_PROTOCOL = "TLS"; 

    private SSLSocketFactory sslSocketFactory; 

    /** 
    * getSSLSocketFactory - populates SSLSocketFactory (if empty in this 
    * instance) and returns the same. 
    * 
    * @return SSLSocketFactory 
    * @throws IOException 
    *    IOException 
    */ 
    public SSLSocketFactory getSSLSocketFactory() throws IOException { 
     if (this.sslSocketFactory == null) { 
      InputStream certificateInputStream = null; 
      try { 
       ClassLoader classLoader = MyClass.class.getClassLoader(); 
       if (classLoader != null) { 
        String certificateFilePath = "certificateFilePath"; 

        certificateInputStream = classLoader.getResourceAsStream(certificateFilePath); 

        String ksPwd = "ksPwd"; 
        KeyStore clientStore = KeyStore.getInstance(KEYSTORE_TYPE); 
        clientStore.load(certificateInputStream, ksPwd.toCharArray()); 

        KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); 
        kmf.init(clientStore, ksPwd.toCharArray()); 
        KeyManager[] kms = kmf.getKeyManagers(); 

        SSLContext sslContext = SSLContext.getInstance(SSL_PROTOCOL); 
        sslContext.init(kms, null, new SecureRandom()); 
        this.sslSocketFactory = sslContext.getSocketFactory(); 
       } 
      } catch (CertificateException ce) { 
       LOG.error("Exception while loading secure certificate.", ce); 
       // some code 
      } catch (NoSuchAlgorithmException nsae) { 
       LOG.error("Exception while loading secure certificate.", nsae); 
       // some code 
      } catch (UnrecoverableKeyException uke) { 
       LOG.error("Exception while loading secure certificate.", uke); 
       // some code 
      } catch (KeyStoreException kse) { 
       LOG.error("Exception while loading secure certificate.", kse); 
       // some code 
      } catch (KeyManagementException kme) { 
       LOG.error("Exception while loading secure certificate.", kme); 
       // some code 
      } finally { 
       IOUtils.closeQuietly(certificateInputStream); 
      } 
     } 
     return this.sslSocketFactory; 
    } 

} 

我的测试码

package test; 

import java.io.IOException; 
import java.security.KeyStore; 
import java.security.KeyStoreException; 

import org.junit.Test; 
import org.junit.runner.RunWith; 
import org.powermock.api.mockito.PowerMockito; 
import org.powermock.core.classloader.annotations.PrepareForTest; 
import org.powermock.modules.junit4.PowerMockRunner; 

@RunWith(PowerMockRunner.class) 
@PrepareForTest({KeyStore.class }) 
public class MyClassTest { 

    @Test 
    public void testGetSSLSocketFactory() throws IOException, KeyStoreException { 
     KeyStoreException keyStoreException = new KeyStoreException("Test KeyStoreException"); 
     PowerMockito.mockStatic(KeyStore.class); 
     PowerMockito.when(KeyStore.getInstance("PKCS12")).thenThrow(keyStoreException); 

     MyClass myClass = new MyClass(); 
     myClass.getSSLSocketFactory(); 
     //code to verify mocks 
    } 

} 

堆栈跟踪

11:50:46.270 [main] ERROR test.MyClass - Exception while loading secure certificate. 
java.security.NoSuchAlgorithmException: class configured for KeyManagerFactory: com.sun.net.ssl.internal.ssl.KeyManagerFactoryImpl$SunX509 not a KeyManagerFactory 
    at sun.security.jca.GetInstance.checkSuperClass(GetInstance.java:242) ~[na:1.6.0_30] 
    at sun.security.jca.GetInstance.getInstance(GetInstance.java:221) ~[na:1.6.0_30] 
    at sun.security.jca.GetInstance.getInstance(GetInstance.java:147) ~[na:1.6.0_30] 
    at javax.net.ssl.KeyManagerFactory.getInstance(KeyManagerFactory.java:121) ~[na:1.6] 
    at test.MyClass.getSSLSocketFactory(MyClass.java:55) ~[na:na] 
    at test.MyClassTest.testGetSSLSocketFactory(MyClassTest.java:43) [na:na] 
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.6.0_30] 
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) ~[na:1.6.0_30] 
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) ~[na:1.6.0_30] 
    at java.lang.reflect.Method.invoke(Method.java:597) ~[na:1.6.0_30] 
    at org.junit.internal.runners.TestMethod.invoke(TestMethod.java:68) [junit-4.11.jar:na] 
    at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl$PowerMockJUnit44MethodRunner.runTestMethod(PowerMockJUnit44RunnerDelegateImpl.java:310) [na:na] 
    at org.junit.internal.runners.MethodRoadie$2.run(MethodRoadie.java:88) [junit-4.11.jar:na] 
    at org.junit.internal.runners.MethodRoadie.runBeforesThenTestThenAfters(MethodRoadie.java:96) [junit-4.11.jar:na] 
    at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl$PowerMockJUnit44MethodRunner.executeTest(PowerMockJUnit44RunnerDelegateImpl.java:294) [na:na] 
    at org.powermock.modules.junit4.internal.impl.PowerMockJUnit47RunnerDelegateImpl$PowerMockJUnit47MethodRunner.executeTestInSuper(PowerMockJUnit47RunnerDelegateImpl.java:127) [na:na] 
    at org.powermock.modules.junit4.internal.impl.PowerMockJUnit47RunnerDelegateImpl$PowerMockJUnit47MethodRunner.executeTest(PowerMockJUnit47RunnerDelegateImpl.java:82) [na:na] 
    at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl$PowerMockJUnit44MethodRunner.runBeforesThenTestThenAfters(PowerMockJUnit44RunnerDelegateImpl.java:282) [na:na] 
    at org.junit.internal.runners.MethodRoadie.runTest(MethodRoadie.java:86) [junit-4.11.jar:na] 
    at org.junit.internal.runners.MethodRoadie.run(MethodRoadie.java:49) [junit-4.11.jar:na] 
    at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl.invokeTestMethod(PowerMockJUnit44RunnerDelegateImpl.java:207) [na:na] 
    at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl.runMethods(PowerMockJUnit44RunnerDelegateImpl.java:146) [na:na] 
    at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl$1.run(PowerMockJUnit44RunnerDelegateImpl.java:120) [na:na] 
    at org.junit.internal.runners.ClassRoadie.runUnprotected(ClassRoadie.java:33) [junit-4.11.jar:na] 
    at org.junit.internal.runners.ClassRoadie.runProtected(ClassRoadie.java:45) [junit-4.11.jar:na] 
    at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl.run(PowerMockJUnit44RunnerDelegateImpl.java:118) [na:na] 
    at org.powermock.modules.junit4.common.internal.impl.JUnit4TestSuiteChunkerImpl.run(JUnit4TestSuiteChunkerImpl.java:101) [powermock-module-junit4-common-1.5.1.jar:na] 
    at org.powermock.modules.junit4.common.internal.impl.AbstractCommonPowerMockRunner.run(AbstractCommonPowerMockRunner.java:53) [powermock-module-junit4-common-1.5.1.jar:na] 
    at org.powermock.modules.junit4.PowerMockRunner.run(PowerMockRunner.java:53) [powermock-module-junit4-1.5.1.jar:na] 
    at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50) [.cp/:na] 
    at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38) [.cp/:na] 
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459) [.cp/:na] 
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:675) [.cp/:na] 
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382) [.cp/:na] 
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192) [.cp/:na] 

回答

1

密钥库(java.security.KeyStore中)是一种系统类。因此,请按照“Mocking system classes”中指定的方法使用该方法来模拟系统类。

所以,你的测试代码将如下......

@RunWith(PowerMockRunner.class) 
@PrepareForTest(MyClass.class) 
public class MyClassTest { 

    @Test 
    public void testGetSSLSocketFactory() throws IOException, KeyStoreException { 
     KeyStoreException keyStoreException = new KeyStoreException("Test KeyStoreException"); 
     PowerMockito.mockStatic(KeyStore.class); 
     PowerMockito.when(KeyStore.getInstance("PKCS12")).thenThrow(keyStoreException); 

     MyClass myClass = new MyClass(); 
     myClass.getSSLSocketFactory(); 
     //code to verify mocks 
    } 

} 

的使用注意事项“MyClass的”(即使用系统类的类),而不是“密钥库”(系统类的需要被嘲笑)在“@PrepareForTest(<> .class)”。