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

我使用JMockit 1.1,我想做的就是调用私有方法并测试返回值。 但是,我无法从JMockit De-Encapsulation示例中确切了解如何执行此操作。

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

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

我的测试代码如下。

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

而我得到的错误是:

java.lang.IllegalStateException:此时缺少对mocked类型的调用; 请确保仅在声明合适的模拟字段或参数后才会出现此类调用

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

我认为你这太复杂了。 您根本不应该使用Expectations块。 你需要做的就是这样:

 @Test public void testParsingForCommas() { StringToTransaction tested = new StringToTransaction(); List expected = new ArrayList(); // Add expected strings list here.. List actual = Deencapsulation.invoke(tested, "parseTransactionString", "blah blah"); assertEquals(expected, actual); } 

基本上,通过Deencapsulation调用私有方法并测试实际值是否等于预期值。 就像你公开的方法一样。 没有嘲笑,所以不需要Expectations阻止。

此时,我不知道JMockit是否可以或应该用于此。 测试我的私有方法可以使用普通的旧reflection来完成,尽管我开始本练习以了解JMockit(并测试我的代码)。 如果JMockit不能用于此,那么我可以使用reflection代替。

 @Test public void testParsingForCommas() throws Exception { StringToTransaction tested = new StringToTransaction(); ArrayList 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私有方法时invoke会爆炸。

 declaredMethod.setAccessible(true); 

但你想知道什么是真的很酷? 如果你不调用setAccessible(true) ,它将会爆发java.lang.StackOverflowError ! 🙂

为什么要直接测试私有方法? 大多数时候API方法即公共接口方法作为私有方法进行unit testing, 也将与它们一起进行间接测试 。 您可以在私有方法中放置具有期望值的断言语句,您可以在公共方法中调用它们。 因此,如果assert失败,您确定私有方法存在一些问题。 所以你不需要单独测试它。