我试图通过模拟KeyStore和KeyStore.getInstance(KEYSTORE_TYPE)来覆盖KeyStoreException块。但是当我嘲笑KeyStore时,我得到的是NoSuchAlgorithmException。能否帮助我覆盖异常块。
我经历过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]
答案 0 :(得分:2)
KeyStore(java.security.KeyStore)是一个System类。因此,使用“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
}
}
请注意在“@PrepareForTest(<> .class)”中使用“MyClass”(使用系统类的类)而不是“KeyStore”(需要模拟的系统类)。