java - 如何模拟 keystore 类并将模拟行为分配给其方法?

标签 java unit-testing mockito keystore powermockito

我有以下方法,我需要为其编写单元测试。但我无法监视类 KeyStore。它抛出以下异常。

org.mockito.exceptions.base.MockitoException: Unable to create mock instance of type 'KeyStore'

不过我可以 mock 它。但是当我为模拟方法分配行为时,它会抛出异常。我调用的方法和得到的异常如下。

when(keyStoreMock.getCertificate(anyString())).thenReturn(certificateMock);

 java.security.KeyStoreException: Uninitialized keystore

doNothing().when(keyStoreMock).load(any(InputStream.class),Mockito.any(char[].class));

 java.lang.NullPointerException

下面是我正在尝试测试的方法。

     public boolean verifySignature(String filePath, String extractContentsPath, String csvParams)
                throws ServiceSDKException {
            boolean result = false;
            String typeOfCertificateStore = "";
            String certificateStoreProvider = "";
            String certificateName = "";
            SignerInformationVerifier verifier = null;
            if (filePath != null && extractContentsPath != null && csvParams != null && !filePath.isEmpty()
                    && !extractContentsPath.isEmpty() && !csvParams.isEmpty()) {
                try {
                    String[] receivedParams = csvParams.split(",");
                    typeOfCertificateStore = receivedParams[0];
                    certificateStoreProvider = receivedParams[1];
                    certificateName = receivedParams[2];
                } catch (ArrayIndexOutOfBoundsException e) {
                    throw new ServiceSDKException("csvParams should have type of certificate store, certificate store provider and certificate name respectively", e);
                }
                try {
                    Path signedDataFilePath = Paths.get(filePath);
                    Path pathToExtractContents = Paths.get(extractContentsPath);

                    KeyStore msCertStore = KeyStore.getInstance(typeOfCertificateStore, certificateStoreProvider);
                    msCertStore.load(null, null);
                    try {
                        verifier = new JcaSimpleSignerInfoVerifierBuilder()
                                .setProvider(certificateStoreProvider)
                                .build(((X509Certificate) msCertStore.getCertificate(certificateName)));
                    } catch (Exception e) {
                        throw new ServiceSDKException("Exception occurred when building certificate",e);
                    }
                    verify(signedDataFilePath, pathToExtractContents, verifier);
                    result = true;
                } catch (KeyStoreException | NoSuchProviderException | IOException | NoSuchAlgorithmException
                        | CertificateException e) {
                    result = false;
                    throw new ServiceSDKException("Exception occurred while preparing to verify signature " , e);
                }
            } else {
                throw new ServiceSDKException("FilePath,extract contents path or csv params cannot be empty or null");
            }
            return result;
        }

如何模拟 KeyStore 及其方法行为?请指教。

使用 MOCKITO 的新测试方法:

@PrepareForTest(KeyStore.class)
    @Test
    public void should_verify_signature_when_verifySignature_called_with_fileName_and_certificate_details_in_verifySignature_method() throws Exception {
        PowerMockito.mockStatic(KeyStore.class);

        KeyStore keyStoreMock = PowerMockito.mock(KeyStore.class);
        PowerMockito.when(KeyStore.getInstance(anyString())).thenReturn(keyStoreMock);
        Mockito.doNothing().when(keyStoreMock).load(any(InputStream.class), Mockito.any(char[].class));
        Certificate certificateMock = Mockito.mock(Certificate.class);
        when(keyStoreMock.getCertificate(anyString())).thenReturn(certificateMock);

        PowerMockito.when(KeyStore.getInstance("Windows-MY", "MoonMSCAPI")).thenReturn(keyStoreMock);
        boolean result = signatureUtil.verifySignature("src//test//java//Updates.zip.signed.pkcs7"
                , "src//test//java//Updates-retrieved.zip", "Windows-MY,MoonMSCAPI,Software View Certificate Authority");
        Assert.assertTrue(result);

    }

最佳答案

您可以在不使用 PowerMock 的情况下模拟它,但方式稍微复杂一点:

KeyStoreSpi keyStoreSpiMock = mock(KeyStoreSpi.class);
KeyStore keyStoreMock = new KeyStore(keyStoreSpiMock, null, "test"){ };
keyStoreMock.load(null);  // this is important to put the internal state "initialized" to true

从现在开始,您只需模拟 keyStoreSpiMock,例如:

when(keyStoreSpiMock.engineGetKey(any(), any())).thenReturn(mock(Key.class);

关于java - 如何模拟 keystore 类并将模拟行为分配给其方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36354270/

相关文章:

java - 是否可以覆盖 JUnit 中的预期异常?

java - IntelliJ IDEA,jbehave 支持插件找不到声明去

c# - 单元测试功能

c# - 我如何模拟 Directory.GetFiles?

c# - 我如何最小起订量 System.IO.FileInfo 类...或任何其他没有接口(interface)的类?

android - java.lang.NoClassDefFoundError : org. 模拟.Mockito

java - 为什么java不让我调用这个 protected 函数

java - 在不使用上下文的情况下访问 Webapp 文件夹中的文件

java - 为什么我不能以这种方式在 for 循环中定义变量?

java - Mockito NotaMockException