Изменение частного участника на значение по умолчанию для тестирования

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

РЕДАКТИРОВАТЬ: Все вы, ребята, говорите правду. Но классы часто имеют вспомогательные частные методы. И эти методы могут быть сложными, поэтому их нужно протестировать. И это слишком плохо - проверить общедоступные методы для обеспечения правильной работы для частных сложных методов. Вы так не считаете?

Ответ 1

Я вообще предпочитаю писать свои классы и тесты таким образом, что писать тесты против публичного API имеет смысл. Поэтому, в основном, я говорю, если вам нужно получить доступ к приватному состоянию вашего тестируемого класса, вы, вероятно, уже слишком вовлечены во внутренности этого класса с вашим тестом.

Ответ 2

Нет, это не так. Поскольку изменение тестового объекта может изменить результат. Если вам действительно нужно вызывать частных членов или методы во время теста, безопаснее добавлять аксессуар. Это все еще изменяет класс, но с меньшим риском. Пример:

private void method() { /* ... */ }

// For testing purpose only, remove for production
@Deprecated  // just another way to create awareness ;)
void testMethod() {
   method();
}

ОК - еще одно решение, если вам нужно проверить частные методы: вы можете вызвать любой метод с API-интерфейсом отражения и создания экземпляров.

Предполагая, что:

public class SomeClass {
  private Object helper(String s, String t) { /* ... +/ }
}

то мы можем проверить его как

@Test public void testHelper() {
   try {
     SomeClass some = new SomeClass();
     Method helperMethod = some.getClass().getDeclaredMethod("helper", String.class, String,class);
     helperMethod.setAccessible(true);
     Object result = helperMethod.invoke(some, "s", "t");
     // do some assert...

   catch(Exception e) {
     // TODO - proper exception handling
   }
}

Ответ 3

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

   MainObject.cs
    class MainObject
    {
        protected int MethodOne();    // Should have been private.
        ....
    }
    TestMainObject.cs
    class ExposeMainObject : MainObject
    {
        public int MethodOne();
    }
    class TestMainObject
    {
        public void TestOne()
        {
        }
    }

Поскольку тестовые объекты не отправляются, я не вижу проблемы с ним, но если есть, скажите мне.

Ответ 4

Тестирование модификаторов конфиденциальности козырей. Действительно, как часто возникает ошибка, вызванная "слишком большой" видимостью для метода? По сравнению с ошибками, вызванными методом, который не был полностью протестирован?

Было бы неплохо, если бы у Java была опция "friend", например С++. Но ограничение в языке никогда не должно быть оправданием для того, чтобы не тестировать что-то.

Майкл Перс возобладает в этой дискуссии в разделе "Эффективная работа с устаревшим кодом" (отличная книга) и предполагает, что это может быть запах подкласса, который хочет быть извлеченным (и иметь общедоступные методы).

В нашем магазине (~ 1M LOC) мы заменим 'private' на "/TestScope/" как индикатор того, что метод должен быть фактически закрытым, но все же проверяемым.

Попытка обойти 'private' с отражением - это ИМХО запах. Это делает тесты сложнее писать, читать и отлаживать, чтобы сохранить "фетиш" конфиденциальности, в котором вы все равно работаете. Зачем беспокоиться?