2016-09-23 94 views
0

我正在用Mockito寫一個JUnit。但在線間諜方法調用實際方法

when(encryptDecryptUtil.getKeyFromKeyStore(any(String.class))).thenReturn(keyMock); 

它調用實際的方法,這是導致測試失敗。有趣的是,當when()... thenReturn()statemnts被執行時,它直接在測試用例開始時進行實際調用。你能告訴我如何解決這個問題嗎?我的測試如下

@Test 
public void testDecryptData_Success() throws NoSuchPaddingException, NoSuchAlgorithmException, BadPaddingException, IllegalBlockSizeException { 
    encryptDecryptUtil = spy(new EncryptDecryptUtil()); 
    Key keyMock = Mockito.mock(Key.class); 
    when(encryptDecryptUtil.getKeyFromKeyStore(any(String.class))).thenReturn(keyMock); 
    String inputData = "TestMessage"; 
    String version = GetPropValues.getPropValue(PublisherConstants.KEYSTORE_VERSION); 
    byte[] enCryptedValue= new byte[] {9,2,5,8,9}; 
    Cipher cipherMock = Mockito.mock(Cipher.class); 
    when(Cipher.getInstance(any(String.class))).thenReturn(cipherMock); 
    when(cipherMock.doFinal(any(byte[].class))).thenReturn(enCryptedValue); 
    String encryptedMessage = encryptDecryptUtil.encryptData(inputData); 
    assert(encryptedMessage.contains(version)); 
    assertTrue(!encryptedMessage.contains(inputData)); 
} 

在第三行它自己,它調用實際的方法。主代碼如下。

public class EncryptDecryptUtil { 
private String publicKeyStoreFileName = 

GetPropValues.getPropValue(PublisherConstants.KEYSTORE_PATH); 
    private String pubKeyStorePwd = "changeit"; 
    private static final String SHA1PRNG = "SHA1PRNG"; 
    private static final String pubKeyAlias="jceksaes"; 
    private static final String JCEKS = "JCEKS"; 
    private static final String AES_PADDING = "AES/CBC/PKCS5Padding"; 
    private static final String AES = "AES"; 
    private static final int CONST_16 = 16; 
    private static final int CONST_0 = 0; 
    private static final String KEY_STORE = "aes-keystore"; 
    private static final String KEY_STORE_TYPE = "jck"; 
    private static final Logger logger = Logger.getLogger(KafkaPublisher.class); 

    public Key getKeyFromKeyStore(String keystoreVersion) { 

     KeyStore keyStore = null; 
     Key key = null; 
     try { 
      keyStore = KeyStore.getInstance(JCEKS); 
      FileInputStream stream = null; 
      stream = new FileInputStream(publicKeyStoreFileName+KEY_STORE+PublisherConstants.UNDERSCORE+keystoreVersion+PublisherConstants.DOT+KEY_STORE_TYPE); 
      keyStore.load(stream, pubKeyStorePwd.toCharArray()); 
      stream.close(); 
      key = keyStore.getKey(pubKeyAlias, pubKeyStorePwd.toCharArray()); 
     } catch (KeyStoreException e) { 
      e.printStackTrace(); 
     } 
     catch (FileNotFoundException e) { 
      logger.error("Error Inside getKeyFromKeyStore, Exception = " + e); 
      e.printStackTrace(); 
     } catch (CertificateException e) { 
      logger.error("Error Inside getKeyFromKeyStore, Exception = " + e); 
      e.printStackTrace(); 
     } catch (UnrecoverableKeyException e) { 
      logger.error("Error Inside getKeyFromKeyStore, Exception = " + e); 
      e.printStackTrace(); 
     } catch (NoSuchAlgorithmException e) { 
      logger.error("Error Inside getKeyFromKeyStore, Exception = " + e); 
      e.printStackTrace(); 
     } catch (IOException e) { 
      logger.error("Error Inside getKeyFromKeyStore, Exception = " + e); 
      e.printStackTrace(); 
     } 
     return key; 
    } 

    public String encryptData(String data) { 
     String keystoreVersion = GetPropValues.getPropValue(PublisherConstants.KEYSTORE_VERSION); 
     SecretKey secKey = new SecretKeySpec(getKeyFromKeyStore(keystoreVersion).getEncoded(), AES); 
     String base64EncodedEncryptedMsg = null; 
     Cipher cipher = null; 

     try { ------- Logic -------------------} 
catch() { } 
} 
} 

回答

1

看一看在該Spy documentation的部分「的奸細實物重要疑難雜症」。

本質上,你不能在間諜中使用when(...).thenReturn(...)模式,因爲正如你發現的那樣,它會調用真正的方法!

相反,您可以使用不同的圖案,其不完全一樣的東西:

doReturn(...).when(spy).someMethod(); 

所以,你的例子:

doReturn(keyMock).when(encryptDecryptUtil).getKeyFromKeyStore(any(String.class)); 

一些建議是無關你的問題:如果我讀您的代碼正確,然後EncryptDecryptUtil是您正在測試的類。作爲一般規則,您不應該在實際測試的對象上嘲笑,存根或窺探,因爲那樣您就不會測試真正的對象。您實際上正在測試由Mockito庫創建的對象的版本。此外,這是一種罕見的模式,會使您的測試難以閱讀和維護。如果你發現自己必須這樣做,那麼最好的辦法就是重構你的代碼,這樣你正在嘲笑(或者正在監視)的方法和你正在測試的方法在不同的類中。

+0

感謝您的解決方案..!我以前嘗試過doReturn(..),但以錯誤的方式嘗試過。 關於你的建議,我明白,但不幸的是,這個類不使用任何Apring或高級框架。我只寫了基本的Java程序,這使得編寫junit非常困難。它有一堆使用新的Constructor()初始化的對象;這是一個很大的痛苦。我試圖用powermockito來取得它不成功,所以我去了SPY()。如果你知道有更好的方法來用new()來完成對這個對象的初始化,我會明白這一點 – user3452558

相關問題