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

2022-09-02 19:51:56

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

我尝试测试的方法是此类中的私有方法:

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:此时缺少对模拟类型的调用;请确保此类调用仅在声明合适的模拟字段或参数后出现

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


答案 1

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

@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调用私有方法,并测试实际值是否等于预期。就像你一样,如果该方法是公开的。没有进行任何模拟,因此不需要期望块。


答案 2

在这一点上,我不知道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);
}

调用 to 在这里很重要,否则调用私有方法时会爆炸。setAccessible(true)invoke

declaredMethod.setAccessible(true);

但你想知道什么才是真正酷的?如果你不打电话,它会用!:)setAccessible(true)java.lang.StackOverflowError