我有遗留方法 Thread.currentThread() .getContextClassLoader() .getResourceAsStream("security/" + keystoreName),所以当我模拟类加载器时,我正在破坏真正的类加载器,接下来的测试不起作用,所以我有 2 个解决方案,但不知道如何实现它。第一个以某种方式模拟/使用类加载器并首先获得真正的类加载器,并在测试后将真实的类加载器设置回线程。第二个以某种方式创建文件并在测试中使用它,我不知道该怎么做。请帮助解决方案和做什么
实用类的方法
public static KeyPair getKeyPairFromKeystore(JwtConfigProperties jwtConfigProperties,
KeystoreConfigProperties keystoreConfigProperties) {
log.info( "Called get keypair from keystore");
KeyStore.PrivateKeyEntry privateKeyEntry = null;
Certificate cert = null;
String keystoreName = keystoreConfigProperties.getName();
try (InputStream in = Thread.currentThread()
.getContextClassLoader()
.getResourceAsStream("security/" + keystoreName)
) {
if (in == null) {
log.info("Input file is null!");
throw new NoSuchElementException("Input file is null");
}
char[] keystorePassword = keystoreConfigProperties.getPassword().toCharArray();
char[] jwtPassword = jwtConfigProperties.getPassword().toCharArray();
String jwtAlias = jwtConfigProperties.getAlias();
//enforcing jceks
KeyStore keyStore = KeyStore.getInstance("JCEKS");
keyStore.load(in, keystorePassword);
KeyStore.PasswordProtection keyPassword = new KeyStore
.PasswordProtection(jwtPassword);
privateKeyEntry = (KeyStore.PrivateKeyEntry) keyStore.getEntry(jwtAlias, keyPassword);
cert = keyStore.getCertificate(jwtAlias);
log.debug("Public key: {}", cert.getPublicKey().toString());
} catch (KeyStoreException | IOException | NoSuchAlgorithmException
| CertificateException | UnrecoverableEntryException e) {
log.error("Error message: {}, Exception: {}", e.getMessage(), e);
}
return new KeyPair(Objects.requireNonNull(cert).getPublicKey(),
Objects.requireNonNull(privateKeyEntry).getPrivateKey());
}
JwtConfigProperties & KeystoreConfigProperties 它是来自 application.yml 的配置属性
我的测试
@RunWith(MockitoJUnitRunner.class)
public class KeystoreUtilTest {
@Mock
private ClassLoader newLoader;
@Mock
private InputStream in;
@Mock
private KeyStore keystore;
@Test
public void testGetKeyPairFromKeystore_validPublicKey() throws KeyStoreException {
Certificate certificate = mock(Certificate.class);
PublicKey publicKey = mock(PublicKey.class);
JwtConfigProperties jwtConfigProperties = new JwtConfigProperties();
jwtConfigProperties.setAlias("alias");
jwtConfigProperties.setPassword("password");
KeystoreConfigProperties keystoreConfigProperties = new KeystoreConfigProperties();
keystoreConfigProperties.setName("name");
keystoreConfigProperties.setPassword("password");
Thread.currentThread().setContextClassLoader(newLoader);
when(newLoader.getResourceAsStream("security/" + keystoreConfigProperties.getName())).thenReturn(in);
try (MockedStatic<KeyStore> keyStoreMockedStatic = mockStatic(KeyStore.class)) {
keyStoreMockedStatic
.when(() -> KeyStore.getInstance("JCEKS"))
.thenReturn(keystore);
keyStoreMockedStatic
.when(() -> KeyStore.getInstance("JCEKS").getCertificate("alias"))
.thenReturn(certificate);
keyStoreMockedStatic
.when(() -> KeyStore.getInstance("JCEKS").getCertificate("alias").getPublicKey())
.thenReturn(publicKey);
assertThrows(NullPointerException.class,
() -> KeystoreUtil.getKeyPairFromKeystore(jwtConfigProperties, keystoreConfigProperties));
verify(keystore, times(2)).getCertificate("alias");
keyStoreMockedStatic
.verify(() -> KeyStore.getInstance("JCEKS"), times(3));
}
}
在测试中,我在嘲笑Classloader,但是真正的人停止了他的工作,并且在这个测试之后没有开始测试
不要嘲笑它。注入一个函数作为参数。
public static KeyPair getKeyPairFromKeystore(JwtConfigProperties jwtConfigProperties,
KeystoreConfigProperties keystoreConfigProperties,
Function<String, InputStream> getInputStream
) {
//...
try (InputStream in = getInputStream.apply("security/" + keystoreName)) {
//...
}
}
在你的真实代码中,传递一个函数
getKeyPairFromKeystore(..., ...,
str -> Thread.currentThread()
.getContextClassLoader()
.getResourceAsStream(str)
)
在您的测试中,传递任何函数返回您想要用于测试的 InputStream。