Подтвердить что ты не робот

JUnit: тестирование класса-помощника только с помощью статических методов

Я тестирую класс-помощник только с статическими методами с JUnit4 и Cobertura. Методы тестирования были легкой задачей и уже выполнены.

Однако, cobertura показывает, что класс не полностью покрывается испытаниями, поскольку он не создается нигде.

Я не хочу создавать экземпляр этого класса (это вспомогательный класс), поэтому первое решение - скрыть конструктор (что обычно является хорошим подходом для вспомогательного класса).

Затем cobertura жалуется, что пустой частный конструктор не покрывается тестами.

Есть ли какое-либо решение для покрытия 100% кода для такой ситуации?

Покрытие кода требуется от управления верхним уровнем (в данном случае), поэтому для меня получение 100% для этого конкретного класса весьма полезно.

4b9b3361

Ответ 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

Нет.

Если вы не вызываете частный конструктор явно (это будет плохой код), вы не сможете покрыть эти строки.