Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/unit-testing/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 调用Mockito doNothing方法时调用Real方法_Java_Unit Testing_Mockito_Powermock_Powermockito - Fatal编程技术网

Java 调用Mockito doNothing方法时调用Real方法

Java 调用Mockito doNothing方法时调用Real方法,java,unit-testing,mockito,powermock,powermockito,Java,Unit Testing,Mockito,Powermock,Powermockito,我试图模拟类密钥库。在模拟之后,我不希望在调用load方法时发生任何事情。因此,我写了以下几行来实现这一点 @PrepareForTest(KeyStoreFactory.class) @Test public void should_verify_signature_when_verifySignature_called_with_fileName_and_certificate_details_in_verifySignature_method

我试图模拟类密钥库。在模拟之后,我不希望在调用load方法时发生任何事情。因此,我写了以下几行来实现这一点

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

            KeyStore keyStoreMock = PowerMockito.mock(KeyStore.class);
            PowerMockito.when(KeyStoreFactory.getInstance(anyString(), anyString())).thenReturn(keyStoreMock);
            Mockito.doNothing().when(keyStoreMock).load(Mockito.any(InputStream.class), Mockito.any(char[].class));
            Certificate certificateMock = Mockito.mock(Certificate.class);
            when(keyStoreMock.getCertificate(anyString())).thenReturn(certificateMock);
            boolean result = signatureUtil.verifySignature("src//test//java//Updates.zip.signed.pkcs7"
                    , "src//test//java//Updates-retrieved.zip", "Windows-MY,SunMSCAPI,someName");
            Assert.assertTrue(result);

        }
但是load方法引发了空指针异常。然后,当我调试时,我发现真正的方法正在被调用,尽管我已经指定mockito不被调用。我做错了什么?请给我一些建议

下面是我编写测试的方法

    @Override
        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 = KeyStoreFactory.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 (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;
        }
这是整个测试类:

@RunWith(PowerMockRunner.class)
public class SignatureUtilImplTest {

    SignatureUtilImpl signatureUtil = new SignatureUtilImpl();

@PrepareForTest({KeyStoreFactory.class, SignatureUtilImpl.class})
    @Test
    public void should_verify_signature_when_verifySignature_called_with_fileName_and_certificate_details_in_verifySignature_method() throws Exception {
        CMSSignedDataParser spMock = PowerMockito.mock(CMSSignedDataParser.class);
        SignerInformationVerifier verifierMock = Mockito.mock(SignerInformationVerifier.class);
        SignatureUtilImpl signatureUtilSpy = Mockito.spy(new SignatureUtilImpl());
        KeyStore keyStoreMock = PowerMockito.mock(KeyStore.class);
        PowerMockito.mockStatic(KeyStoreFactory.class);
        PowerMockito.when(KeyStoreFactory.getInstance(anyString(), anyString())).thenReturn(keyStoreMock);
        SignerInformation signerInformationMock = Mockito.mock(SignerInformation.class);
        Collection<SignerInformation> collection = new ArrayList();
        collection.add(signerInformationMock);

        Mockito.doCallRealMethod().when(signatureUtilSpy).verifySignature("src/test/java/Updates.zip.signed.pkcs7"
                , "src/test/java/Updates-retrieved.zip", "Windows-MY,SunMSCAPI,someName");
        Mockito.doNothing().when(signatureUtilSpy).loadKeyStore();
        Mockito.doReturn(verifierMock).when(signatureUtilSpy).getSignerInformationVerifier(anyString(), anyString());
        Mockito.doReturn(spMock).when(signatureUtilSpy).getDataParser(any(DigestCalculatorProvider.class), any(FileInputStream.class));
        Mockito.doReturn(collection).when(spMock).getSignerInfos().getSigners();
        Mockito.doReturn(true).when(signerInformationMock).verify(verifierMock);
        //PowerMockito.doNothing().when(signatureUtilSpy, "verify", any(Path.class),any(Path.class),any(SignerInformationVerifier.class));

//        PowerMockito.doReturn(true).when(signatureUtilSpy, PowerMockito.method(SignatureUtilImpl.class, "verify",Path.class,Path.class, SignerInformationVerifier.class))
//                .withArguments(any(Path.class),any(Path.class),any(SignerInformationVerifier.class));

        boolean result = signatureUtilSpy.verifySignature("src/test/java/Updates.zip.signed.pkcs7"
                , "src/test/java/Updates-retrieved.zip", "Windows-MY,SunMSCAPI,someName");
        Assert.assertTrue(result);
}

}
@RunWith(PowerMockRunner.class)
公共类SignatureUtilImplTest{
SignatureUtilImpl signatureUtil=新的SignatureUtilImpl();
@PrepareForTest({Keystrefactory.class,SignatureUtilImpl.class})
@试验
public void应在\u verifySignature方法()中使用\u fileName\u和\u certificate\u details\u调用\u时\u验证\u签名\u引发异常{
CMSSignedDataParser spMock=PowerMockito.mock(CMSSignedDataParser.class);
SignerInformationVerifier-verifierMock=Mockito.mock(SignerInformationVerifier.class);
SignatureUtilImpl signatureUtilSpy=Mockito.spy(新的SignatureUtilImpl());
keystorekeystoremock=PowerMockito.mock(KeyStore.class);
mockStatic(keystefactory.class);
when(KeyStoreFactory.getInstance(anyString(),anyString())。然后返回(keyStoreMock);
SignerInformation SignerInformation mock=Mockito.mock(SignerInformation.class);
集合集合=新的ArrayList();
collection.add(signerInformationMock);
Mockito.doCallRealMethod().when(signatureUtilSpy).verifySignature(“src/test/java/Updates.zip.signed.pkcs7”
,“src/test/java/Updates retrieved.zip”,“Windows MY,SunMSCAPI,someName”);
Mockito.doNothing().when(signatureUtilSpy.loadKeyStore();
Mockito.doReturn(verifierMock).when(signatureUtilSpy).getSignerInformationVerifier(anyString(),anyString());
doReturn(spMock).when(signatureUtilSpy).getDataParser(any(DigestCalculatorProvider.class)、any(FileInputStream.class));
Mockito.doReturn(collection).when(spMock.getSignerInfos().getSigners();
Mockito.doReturn(true).when(signerInformationMock).verify(verifierMock);
//当(signatureUtilSpy,“verify”、any(Path.class)、any(Path.class)、any(SignerInformationVerifier.class));
//PowerMockito.doReturn(true).when(signatureUtilSpy,PowerMockito.method(SignatureUtilImpl.class,“验证”,Path.class,Path.class,SignerInformationVerifier.class))
//.withArguments(any(Path.class)、any(Path.class)、any(SignerInformationVerifier.class));
布尔结果=signatureUtilSpy.verifySignature(“src/test/java/Updates.zip.signed.pkcs7”
,“src/test/java/Updates retrieved.zip”,“Windows MY,SunMSCAPI,someName”);
Assert.assertTrue(结果);
}
}

我认为这有助于:

在SignatureUtil中创建另一个方法:

public KeyStore loadKeyStore(...){
  KeyStore msCertStore = KeyStoreFactory.getInstance(typeOfCertificateStore,certificateStoreProvider);
  msCertStore.load(null, null);
}
在你的测试课上,像下面这样做

Mockito.doNothing().when(signatureUtilMock).loadKeyStore(anyString(), anyString());
这是为我工作的代码

package com.foo;

import java.io.IOException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;


public class KeyStoreService {
  public KeyStoreService(){

  }

  public void load() throws KeyStoreException, NoSuchAlgorithmException, CertificateException, IOException{
    System.out.println("start");
    KeyStore ks = KeyStore.getInstance("");
    ks.load(null, null);
    System.out.println("end");
 }


}
测试班


KeyStore
是一个系统类,因此要模拟它,应该将调用系统类的
类添加到
@PrepareForTest
。据我所知,在您的情况下,SignatureUtilImpl应该在
@prepareForest
中。但可能还有另一个类也叫这个系统类

顺便说一句,由于PowerMock是如何模拟系统类的,您在这一行中可能会遇到cast问题

new JcaSimpleSignerInfoVerifierBuilder()
                            .setProvider(certificateStoreProvider)
                            .build(((X509Certificate) msCertStore.getCertificate(certificateName)));

您可以找到更多信息,下面的代码适用于我

PowerMockito.mockStatic(KeyStore.class);
KeyStore mockKeyStore = PowerMockito.mock(KeyStore.class);

PowerMockito.doNothing().when(mockKeyStore).load(Matchers.any(), Matchers.anyObject());
     Mockito.when(KeyStore.getInstance(Matchers.anyString())).thenReturn(mockKeyStore);
doNothing()方法将调用实际方法,如果您不想调用,可以使用。它将禁止调用无返回方法

doNothing().when(switchMock).finalVoidMethod(channelId);
改变

suppress(method(SignatureUtilImpl.class, "loadKeyStore"));

我假设signatureUtil在内部调用keysterfactory方法。在signatureUtil中模拟使用KSF的特定方法。你能分享签名吗?我添加了你要求的代码。我需要为msCertStore.load方法添加行为模拟(null,null);我该怎么做?Mockito.doNothing().when(KeyStore.load(Mockito.any(InputStream.class)、Mockito.any(char[].class)))无法完成,因为load方法是非静态方法。它不是静态的:(在这种情况下,我将继续为我想要模拟的每个系统类方法创建方法,对吗?而且它的接口可能也不需要是公共的。因此,我们在代码中做的事情不只是为了测试目的吗?您可以将接口设为私有并模拟它。如果我将loadKeyStore方法设为私有,它将不可见。)为了让我模拟它?尝试了这个,PowerMockito.doReturn(true)。当(signatureUtilSpy,“verify”、any(Path.class)、any(Path.class)、any(SignerInformationVerifier.class));但它调用的是实际的方法!它不应该在不执行实际方法的情况下返回true吗?
suppress(method(SignatureUtilImpl.class, "loadKeyStore"));