2016-04-04 4 views
2

Я пытаюсь высмеять класс KeyStore. После издевательств я не хочу, чтобы что-то случилось, когда метод загрузки, если он был вызван. Поэтому для этого я написал приведенные ниже строки.Реальный метод, вызываемый при вызове метода Mockito doNothing

 @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); 

     } 

Но метод загрузки выбрасывал исключение исключающего указателя. Затем, когда я отлаживаю, я обнаружил, что реальный метод получает вызов, хотя я указал, что 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); 
} 

} 
+0

Я предполагаю, что подписьUtil внутренне вызывает метод KeyStoreFactory. Отметьте этот конкретный метод в signatureUtil, который использует KSF. Можете ли вы поделиться источником signatureUtil – Sanj

+0

Я добавил запрошенный вами код. Мне нужно добавить поведение mock для метода msCertStore.load (null, null); Как мне это сделать? – mayooran

+0

Mockito.doNothing(). Когда (KeyStore.load (Mockito.any (InputStream.class), Mockito.any (char []. Class))) – Sanj

ответ

2

Я думаю, что это может помочь:

Создать другой метод в 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"); 
} 


} 

Test Class

package com.foo.test; 

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

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

import com.foo.KeyStoreService; 

@PrepareForTest(KeyStoreService.class) 
@RunWith(PowerMockRunner.class) 
public class TestKeyStore { 

    @Test 
    public void test1() throws KeyStoreException, NoSuchProviderException, NoSuchAlgorithmException, CertificateException, IOException{ 
     PowerMockito.mockStatic(KeyStore.class); 
     KeyStore keyStoreMock = PowerMockito.mock(KeyStore.class); 
     KeyStoreService kss = new KeyStoreService(); 
     PowerMockito.when(KeyStore.getInstance(Matchers.anyString(), Matchers.anyString())).thenReturn(keyStoreMock); 
     Mockito.doNothing().when(keyStoreMock).load(Mockito.any(InputStream.class), Mockito.any(char[].class)); 
     kss.load(); 
    } 
} 
+0

В этом случае я буду продолжать создавать методы для каждого метода системного класса, который я хочу высмеять правильно? Также его интерфейс может быть не нужен, чтобы быть общедоступным. Не так ли, как мы делаем вещи в код для тестирования? – mayooran

+0

вы можете сделать интерфейс частным и издеваться над ним. – Sanj

+0

Если я сделаю метод loadKeyStore закрытым, мне не будет видно, чтобы он насмехался над этим? – mayooran

2

KeyStore класс системы, так издеваться НЕГО ClassThatCallsTheSystemClass должно быть добавлено к @PrepareForTest. Как я понимаю, в вашем случае SignatureUtilImpl должен быть в @PrepareForTest. Но могут быть и другие классы, которые также называются системным классом.

Кстати, из-за того, как PowerMock издевается класс системы могут возникнуть проблемы с броском в этой линии

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

Более подробную информацию вы можете найти here и here

0

Следующий код работает для меня

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); 

 Смежные вопросы

  • Нет связанных вопросов^_^