2016-09-23 48 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

相关问题