Как проверить метод void, который изменяет только переменные-члены частного класса? - PullRequest
7 голосов
/ 05 января 2011

Я пытаюсь выполнить модульное тестирование метода в классе, который инициализирует некоторые частные поля:

public void init(Properties props) throws Exception {

    this.language = props.getProperty(Constants.LANGUAGE,Constants.LANGUAGE_DEFAULT);   
    this.country = props.getProperty(Constants.COUNTRY,Constants.COUNTRY_DEFAULT);

        try {
            this.credits = Integer.valueOf(props.getProperty(Constants.CREDITS_OPTION_NAME, Constants.CREDITS_DEFAULT_VALUE));
        } catch (NumberFormatException e) {
            throw new Exception("Invalid configuration: 'credits' does not contain a valid integer value.", e);
        }
        //rest of method removed for sake of simplicity
    }

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

  1. Сделайте открытые методы для доступа к закрытым полям, затем вызовите эти методы после тестирования метода init.
  2. Сделайте модульный тест просто вызовомМетод init, и предположим, что все работает правильно, исключение не было выдано.

Какой, по вашему мнению, идеальный способ проверить этот метод?

Ответы [ 5 ]

9 голосов
/ 05 января 2011

Я хочу подтвердить, что поля языка, страны и кредитов были установлены после вызова init

Некоторая философия: почему вас волнует, правильно ли они установлены? Если ответ «так класс тогда ведет себя правильно», то вы можете проверить, что они были установлены правильно, протестировав это ожидаемое последующее поведение. Однако, если их неправильная установка не имеет никакого эффекта, они являются избыточными, и вы должны удалить их.

Другой автор предложил использовать рефлексию для доступа к приватным полям. Я советую против этого; все, что помечено как private, должно быть деталью реализации класса, и поэтому не должно проверяться напрямую. Вместо этого вы должны протестировать опубликованный API вашего класса. Затем у вас есть свобода его рефакторинга путем изменения (частной) информации о реализации.

9 голосов
/ 05 января 2011

Вы можете использовать отражение, чтобы получить значения приватных полей. Например:

Field field = YourClass.class.getDeclaredField("language");
field.setAccessible(true); //override the access restriction of it being private
field.get(yourObject);

Если на вашем пути к классам есть пружина, вы можете использовать ReflectionUtils / ReflectionTestUtils.

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

Если объект находится в недопустимом состоянии, если поля не заданы, то сам объект должен нести ответственность за обеспечение его валидности путем создания исключения.

4 голосов
/ 05 января 2011

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

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

1 голос
/ 05 января 2011

Лично я бы просто проверил публичные методы.Иногда вам нужно проверить внутренности, но это редко.

Кстати: альтернатива общедоступным получателям - сделать модульное тестирование в одном пакете и предоставить пакет локальным получателям.

1 голос
/ 05 января 2011

Ваш JUnit вызывает метод напрямую? Тогда ссылка на объект свойства будет такой же, вы должны иметь доступ к языку и стране, поскольку кредиты пересчитывают в вашем JUnit.

Публичный метод доступа для частных методов также является хорошим выбором.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...