Вызов частного метода через JMockit для тестирования результата

Я использую 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);
}

Вызов setAccessible(true) здесь важен, или invoke взорвется при вызове частного метода.

declaredMethod.setAccessible(true);

Но вы хотите знать, что действительно круто? Если вы не вызываете setAccessible(true), он взорвется с помощью java.lang.StackOverflowError!:)

Ответ 3

Почему вы хотите напрямую проверить частный метод? В большинстве случаев API-методы, то есть методы публичного интерфейса, тестируются модулем, поскольку частные методы будут также косвенно протестированы вместе с ними. Вы можете поместить выражения assert с ожидаемыми значениями из частных методов, где вы вызываете их в общедоступных методах. Поэтому, если assert не удается, вы уверены, что существует некоторая проблема с частным методом. Поэтому вам не нужно тестировать его отдельно.

Ответ 4

начать с 1.35 (?) jmockit удалил этот вспомогательный метод. по причинам, что это уже не полезно (что я не совсем понимаю)

но да, эта утилита доступна где-то в другом месте

org.springframework.test.util.ReflectionTestUtils

Ответ 5

Как уже упоминалось @Jeff Olson, вы также можете вызвать частные методы компонента, объявив их @Tested.
Вот пример:

'''Джава

@Tested
private YourServiceImplClass serviceImpl;

@Test
public void testPrivateMethod() {

      List<String> expected = new ArrayList<String>();
      // Add expected strings list here..

      List<String> actual = Deencapsulation.invoke(serviceImpl, "yourPrivateMethod", "arguments");
      assertEquals(expected, actual);
}

"""