Я б запропонував вам трохи переробити код. Коли вам доведеться почати думати про використання рефлексії чи іншого виду речей, для того, щоб просто перевірити свій код, з вашим кодом щось не так.
Ви згадали про різні типи проблем. Почнемо з приватних полів. У випадку з приватними полями я б додав новий конструктор і ввів у нього поля. Замість цього:
public class ClassToTest {
private final String first = "first";
private final List<String> second = new ArrayList<>();
...
}
Я б використав це:
public class ClassToTest {
private final String first;
private final List<String> second;
public ClassToTest() {
this("first", new ArrayList<>());
}
public ClassToTest(final String first, final List<String> second) {
this.first = first;
this.second = second;
}
...
}
Це не буде проблемою навіть зі старим кодом. Старий код буде використовувати порожній конструктор, і якщо ви запитаєте мене, код, який переробляється, буде виглядати чистіше, і ви зможете ввести необхідні значення в тест без роздумів.
Тепер про приватні методи. З мого особистого досвіду, коли вам доведеться заглушити приватний метод тестування, тоді цей метод не має нічого спільного в цьому класі. Загальним шаблоном у такому випадку буде загортання його в інтерфейс, наприклад, Callable
а потім ви передаєте цей інтерфейс також у конструктор (з цим численним трюком конструктора):
public ClassToTest() {
this(...);
}
public ClassToTest(final Callable<T> privateMethodLogic) {
this.privateMethodLogic = privateMethodLogic;
}
Переважно все, що я написав, виглядає так, що це схема введення залежності. В моєму особистому досвіді це дуже корисно під час тестування, і я думаю, що такий код чистіший і його буде легше підтримувати. Я б сказав те саме про вкладені класи. Якщо вкладений клас містить важку логіку, було б краще, якби ви перемістили його як приватний клас пакету та ввели його до потрібного класу.
Існує також кілька інших моделей дизайну, які я використовував під час рефакторингу та збереження застарілого коду, але все залежить від випадків перевірки вашого коду. Використання рефлексії здебільшого не є проблемою, але коли у вас є корпоративна програма, яка проходить тестування і запускаються тести перед кожним розгортанням, все стає дуже повільним (це просто дратує, і мені подібні речі не подобаються).
Існує також ін'єкція сетера, але я не рекомендував би його використовувати. Я б краще дотримуватися конструктора і ініціалізувати все, коли це дійсно необхідно, залишаючи можливість вводити необхідні залежності.