JUnit: тестирование класса-помощника только с помощью статических методов
Я тестирую класс-помощник только с статическими методами с JUnit4 и Cobertura. Методы тестирования были легкой задачей и уже выполнены.
Однако, cobertura показывает, что класс не полностью покрывается испытаниями, поскольку он не создается нигде.
Я не хочу создавать экземпляр этого класса (это вспомогательный класс), поэтому первое решение - скрыть конструктор (что обычно является хорошим подходом для вспомогательного класса).
Затем cobertura жалуется, что пустой частный конструктор не покрывается тестами.
Есть ли какое-либо решение для покрытия 100% кода для такой ситуации?
Покрытие кода требуется от управления верхним уровнем (в данном случае), поэтому для меня получение 100% для этого конкретного класса весьма полезно.
Ответы
Ответ 1
Существует несколько решений:
-
Вы можете добавить публичный конструктор и вызвать его из теста. Хотя это и не имеет смысла, это также не повредит (много).
-
Создайте фиктивный статический экземпляр (здесь вы можете вызвать частный конструктор). Ужасно, но вы можете дать поле имя для сообщения о своем намерении (JUST_TO_SILENCE_COBERTURA
- хорошее имя).
-
Вы можете позволить вашему тесту расширить класс-помощник. Это внутренне вызовет конструктор по умолчанию, но ваш вспомогательный класс больше не может быть final
.
Я предлагаю последний подход, особенно потому, что класс больше не может быть final
. Если потребитель вашего кода хочет добавить другой вспомогательный метод, теперь он может расширить существующий класс и получить один дескриптор, чтобы получить все вспомогательные методы. Это создает связь вспомогательных методов, которые связывают намерение (они принадлежат друг другу) - это невозможно, если класс-помощник final
Если вы хотите, чтобы пользователь случайно не создавал экземпляр класса-помощника, сделайте его abstract
вместо использования скрытого конструктора.
Ответ 2
Если вам абсолютно необходимо достичь 100% охвата кода - достоинства этого можно обсудить в другом месте:) - вы можете достичь этого, используя отражение в своих тестах. Как привычка, когда я реализую статический класс, я добавляю в частный конструктор, чтобы гарантировать, что экземпляры класса не могут быть созданы. Например:
/**
* Constructs a new MyUtilities.
* @throws InstantiationException
*/
private MyUtilities() throws InstantiationException
{
throw new InstantiationException("Instances of this type are forbidden.");
}
Тогда ваш тест может выглядеть примерно так:
@Test
public void Test_Constructor_Throws_Exception() throws IllegalAccessException, InstantiationException {
final Class<?> cls = MyUtilties.class;
final Constructor<?> c = cls.getDeclaredConstructors()[0];
c.setAccessible(true);
Throwable targetException = null;
try {
c.newInstance((Object[])null);
} catch (InvocationTargetException ite) {
targetException = ite.getTargetException();
}
assertNotNull(targetException);
assertEquals(targetException.getClass(), InstantiationException.class);
}
В принципе, то, что вы здесь делаете, это получить класс по имени, найти конструкторы этого типа класса, установить его в public (вызов setAccessible
), вызвать конструктор без аргументов, а затем убедиться, что Исключенное целевое исключение - это InstantiationException
.
В любом случае, как вы сказали, 100% -ное требование покрытия кода здесь немного больно, но похоже, что это из ваших рук, так что мало что вы можете с этим поделать. Я фактически использовал подходы, подобные описанным выше, в моем собственном коде, и я нашел это полезным, но не с точки зрения тестирования. Скорее, это просто помогло мне узнать немного больше об отражении, чем я знал раньше:)
Ответ 3
Получение 100% -ного охвата во всех случаях это хорошо, но есть некоторые случаи, когда это невозможно. Конечно, если у вас есть класс, который никогда не создается, Cobertura получит это как не полное тестовое покрытие, потому что эти строки кода действительно находятся в классе, но они не тестируются.
Факт, что вы никогда не вызовете частный конструктор (я предполагаю, что вы скрыли конструктор, сделав его закрытым), поэтому я не стал бы беспокоиться. Тест должен состоять в том, чтобы получить то, что вы ожидаете, и, хотя я согласен, 100% охват хорош, в некоторых случаях (например, это) это не полезно.
Посмотрите 100% покрытие кода.
Ответ 4
Нет.
Если вы не вызываете частный конструктор явно (это будет плохой код), вы не сможете покрыть эти строки.