间谍方法调用实际的方法

时间:2016-09-23 18:23:47

标签: junit mockito spy

我正在和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 个答案:

答案 0 :(得分:1)

看看"关于窥视真实物体的重要问题" Spy documentation

的部分

基本上,你不能将when(...).thenReturn(...)模式与Spies一起使用,因为正如你所发现的那样,它会调用真正的方法!

相反,您使用的是另一种完全相同的模式:

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

所以,举个例子:

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

与您的问题无关的一些建议:如果我正确阅读了您的代码,那么EncryptDecryptUtil就是您正在测试的类。作为一般规则,您不应该模拟,存根或监视您实际测试的对象,因为那样您就不会测试真实对象。您实际上正在测试Mockito库创建的对象版本。此外,它是一种不常见的模式,会使您的测试难以阅读和维护。如果您发现自己必须这样做,那么最好的方法是重构您的代码,以便您正在模拟(或监视)的方法以及您正在测试的方法位于不同的类中。