Модульный тест для блока try-finally

Как мне написать тест для метода getUrl?

public class UrlList {
    private final String[] urls;
    private int index;
    private SecureRandom random;

    public static enum Mode {
        VALUE_1,
        VALUE_2,
        VALUE_3;
    }

    public UrlList(String... urls) {
        if (urls == null || urls.length == 0) {
            throw new IllegalArgumentException("The url list may bot be null or empty!");
        }
        this.urls = urls;
        this.index = 0;
        this.random = new SecureRandom();
    }

    public String getUrl(Mode mode) {
        switch (mode) {
        case VALUE_1:
            return urls[0];
        case VALUE_2:
            return urls[random.nextInt(urls.length)];
        case VALUE_3:
            try {
                return urls[index];
            } finally {
                index = (index + 1) % urls.length;
            }
        default:
            throw new RuntimeException("Unknown mode!");
        }
    }
}

В приведенном выше коде urls представляет собой массив строк.

Главный вопрос в том, как мне протестировать case VALUE_3:?

Потому что в первый раз проверьте index = 0, но после этого значение index изменится на что-то другое в блоке finally, и я хочу снова проверить его с новым значением index в том же классе модульного теста.


person Arthur    schedule 18.06.2014    source источник
comment
Во-первых, если вы собираетесь сделать блок try-finally, вам нужно создать исключение в определении вашей функции.   -  person taylorcressy    schedule 18.06.2014
comment
Я не понимаю, что вы имеете в виду, потому что впервые тестируете nextUrlIndex = 0, но после...   -  person Raedwald    schedule 18.06.2014
comment
Спасибо, taylorcressy. Но что вы думаете о главном вопросе ;)   -  person Arthur    schedule 18.06.2014
comment
Чтобы протестировать метод, вам нужна спецификация этого метода: тест сравнивает фактическое поведение метода с указанным поведением. Таким образом, никто не может сказать вам, как протестировать ваш метод, если вы не предоставите нам его спецификацию.   -  person Raedwald    schedule 18.06.2014
comment
Извините, ребята, я отредактировал код выше. Это правильный код. Перед первым запуском индекс равен нулю, но, например, если вы запускаете метод во второй или третий раз, индекс не равен 0, он изменяется в блоке finally   -  person Arthur    schedule 18.06.2014
comment
предложить String[] urls = {link1, link2, link3}; и индекс = 0 перед запуском первого метода. После первого запуска, когда режим = VAKUE_3, он возвращает URL-адреса [0], но после этого значение индекса изменится в окончательном блоке, и если вы снова запустите метод, когда режим = VAKUE_3, он возвращает URL-адреса [1] и после запуска второго метода он возвращает urls[2], после третьего запуска он снова возвращает urls[0] и так далее.   -  person Arthur    schedule 18.06.2014
comment
Типичным ответом в подобных случаях является только проверка общедоступного интерфейса. Похоже, что nextUrlIndex является закрытым (в противном случае вы могли бы просто проверить его значение из теста), поэтому либо изменение nextUrlIndex оказывает какое-то влияние на общедоступный интерфейс, который вы можете протестировать, либо нет (и фактически это деталь реализации, которая должна остаются непроверенными).   -  person Matthew Strawbridge    schedule 18.06.2014
comment
Я полагаю, что строка nextUrlIndex = (index + 1) % urls.length; должна читаться как index = (index + 1) % urls.length;   -  person Serge Ballesta    schedule 18.06.2014
comment
@Serge Ballesta: Да, вы совершенно правы. Я отредактировал код.   -  person Arthur    schedule 18.06.2014


Ответы (2)


Рассматривали ли вы возможность создания нового экземпляра вашего класса (того, который инкапсулирует index и getUrl) для каждого метода тестирования? Таким образом, каждый тестовый метод начинается заново с index=0...

person Pelit Mamani    schedule 18.06.2014
comment
Привет, Пелит, я изменил код, чтобы теперь вы могли видеть весь класс. - person Arthur; 18.06.2014
comment
Я сделал это, но тестовый класс может просто проверить случай VALUE_3: когда индекс равен 0. А как насчет того, когда индекс изменится, и я хочу проверить его снова? - person Arthur; 18.06.2014

Для ваших тестов вы должны иметь возможность установить значение частной переменной index на (например):

  • значение положительное и меньше urls.length для управления вы получаете index+1
  • url.length -1 для управления вы получаете 0
  • ошибочное значение (отрицательное или большее или равное urls.length), чтобы контролировать получение приемлемого значения (после восстановления после исключения)

Конечно, индекс является закрытым, но вы все равно можете получить доступ через рефлексию.

urlList = new UrlList(...); // in test initialization
...
Field index = UrlList.class.getDeclaredField("index");
index.setAccessible(true);
index.setInt(urlList, i); // to set index
i = index.getInt(urlList); // to get index
person Serge Ballesta    schedule 18.06.2014