通过JMockit调用私有方法来测试结果

通过JMockit调用私有方法来测试结果

问题描述:

我正在使用JMockit 1.1,我想要做的就是调用一个私有方法并测试返回值。但是,我很难理解如何从JMockit De-Encapsulation示例中执行此操作。通过JMockit调用私有方法来测试结果

的方法,我想测试是这个类中的私有方法:

public class StringToTransaction { 
    private List<String> parseTransactionString(final String input) { 
     // .. processing 
     return resultList; 
    } 
} 

而且我的测试代码如下。

@Test 
public void testParsingForCommas() { 
    final StringToTransaction tested = new StringToTransaction(); 
    final List<String> expected = new ArrayList<String>(); 
    // Add expected strings list here.. 
    new Expectations() { 
     { 
     invoke(tested, "parseTransactionString", "blah blah"); 
     returns(expected); 
     } 
    }; 
} 

而且我得到的错误是:

java.lang.IllegalStateException: Missing invocation to mocked type at this point; please make sure such invocations appear only after the declaration of a suitable mock field or parameter

也许我已经在这里误解了整个API,因为我不认为我需要模拟类..只是测试的结果调用私有方法。

我认为你让这个过于复杂。你根本不应该使用期望块。所有你需要做的是这样的:

@Test 
public void testParsingForCommas() { 
    StringToTransaction tested = new StringToTransaction(); 
    List<String> expected = new ArrayList<String>(); 
    // Add expected strings list here.. 

    List<String> actual = Deencapsulation.invoke(tested, "parseTransactionString", "blah blah"); 
    assertEquals(expected, actual); 
} 

基本上,通过Deencapsulation调用私有方法和测试,实际等于预期。就像你会如果该方法是公开的。没有嘲弄正在完成,所以不需要Expectations块。

+0

Hi @JeffOlson - 哪个类是invoke()方法?根据期望,invoke()是受保护的实例方法。或者可能只是使用java.lang.reflect.Method.invoke()并完全忽略JMockit。 – 2013-03-25 09:17:08

+0

最后我明白了...它是'Deencapsulation.invoke',谢谢@JeffOlson,并感谢https:// groups中的Rogerio。 google.com/d/msg/jmockit-users/oEgjW0DfmgU/3pEE1mjt1ncJ。 – 2013-03-25 13:22:20

+0

是的,这是正确的。对不起,我不太清楚,但是你在初始例子中直接使用了'invoke()'(大概是通过静态导入),所以我想我会保持原样。我会更新我的答案,以便将来能够阅读此内容的其他人更加清楚。 – 2013-03-25 14:49:46

为什么要直接测试私有方法?大多数时间API方法,即公共接口方法被单元测试为私有方法将被间接测试以及与他们一起。您可以将声明语句与来自私有方法的期望值放在公用方法中调用它们的位置。所以如果断言失败,你确定私有方法存在一些问题。所以你不需要单独测试它。

+0

嗨@Ankur,我很抱歉,但我正在寻找一个答案,涉及如何正确使用JMockit在这种情况下(甚至是否可以)。我不想讨论为什么我应该或不应该测试私人方法。我明白,通过公共方法使用断言是另一种方式,但这不是我想要在这里解决的。 – 2013-03-24 06:40:15

+0

看看这个:http://*.com/questions/5729973/jmockit-two-mocked-instances-of-the-same-type – 2013-03-24 06:44:42

+0

我可能有点密集@Ankur,但我不能解决如何将该解决方案应用于我的问题。 :)在**测试**的初始化之前放置** Expectations **块导致编译错误:**测试无法解析为变量**。 – 2013-03-24 06:55:26

在这一点上,我不知道JMockit是否可以或应该用于此。测试我的私有方法可以用简单的旧反射来完成,但我开始这个练习来了解JMockit(并测试我的代码)。如果JMockit不能用于此,以下是我如何使用反射。

@Test 
public void testParsingForCommas() throws Exception { 
    StringToTransaction tested = new StringToTransaction(); 
    ArrayList<String> expected = new ArrayList<>(); 
    expected.add("Test"); 

    Method declaredMethod = 
     tested.getClass().getDeclaredMethod("parseTransactionString", 
       String.class); 
    declaredMethod.setAccessible(true); 
    Object actual = declaredMethod.invoke(tested, "blah blah"); 
    assertEquals(expected, actual); 
} 

的调用setAccessible(true)在这里很重要或调用私有方法时invoke将炸毁。

declaredMethod.setAccessible(true); 

但是你想知道什么是真的很酷?如果你不打电话setAccessible(true),它会炸毁java.lang.*Error! :)