Я работаю с устаревшим кодом, где мне нужно реализовать новый обработчик. И в этом обработчике есть объект, который, к сожалению, инициализируется платформой, используя некий жестко закодированный файл свойств, например:
// new code
public class NewHandler extends RootHandler {
Util util = Util.getInstance(); // !!!Problem: throws NPE in unit-testing env
// defined in the legacy framework, can't change its signature
@Override
public void doSth() {
}
}
// legacy code
public class Util {
static public synchronized Util getInstance() {
if (_instance == null) {
_instance = new Util();
}
return _instance;
}
private Util() {
MyObj obj = LegacyCode.load("myConfig.cfg"); // !!!Problem: throws NPE in unit-testing env
...
}
}
Теперь проблема:
в Util()
он всегда загружает файл конфигурации из фиксированного местоположения, поэтому он всегда выдает NPE, когда я запускаю свои модульные тесты, поскольку в пути к классам модульного теста нет «myConfig.cfg».
Один из обходных путей - извлечь бизнес-логику в отдельный метод, передав объект Util, чтобы я мог передавать фиктивные объекты во время тестов:
// new code
public class NewHandler extends RootHandler {
Util util = null;
// defined in the legacy framework, can't change its signature
@Override
public void handle() {
Util util = util.getInstance();
doHandle(util);
}
public void doHandle(Util util) {
...
}
}
// legacy code
public class Util {
...
}
Мой вопрос :
Есть ли другой способ обойти эту проблему, не добавляя метод doHandle ()? Я попробовал следующий код, используя Mockito:
Util myUtil = mock(Util.class);
when(Util.getInstance()).thenReturn(myUtil);
но это не сработало, Util.getInstance () не был заменен на myUtil.
есть мысли?
ОБНОВЛЕНИЕ : Все становится немного грязно, так как я обнаружил, что Util.getInstance () вызывается повсеместно в устаревшей базе кода. Поэтому, даже если у меня есть смоделированный Util в моем новом коде (как было описано Стасом ниже), все равно будет происходить сбой при вызове Util.getInstance () в другом месте.
Очевидно, что я не мог добавить новые конструкторы для каждого отдельного класса в устаревшем коде, который вызывает Util.getInstance ().
По этой причине я спрашиваю: «возможно ли иметь что-то в Mockito, например when (Sth.getInstance ()). ThenReturn (myMock)»
если да, все вызовы Util.getInstance () могут быть поддельными и больше не вызовут проблем.
Хм .... Есть идеи?
*********************************************** ************************
РЕШЕНИЕ : Я думаю, что решение в моем случае PowerMock