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

#java #unit-testing #switch-statement #try-finally

#java #модульное тестирование #switch-оператор #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 значением в том же классе модульного тестирования.

Комментарии:

1. Во-первых, если вы собираетесь выполнить try-finally блок, вам нужно создать исключение в определении вашей функции.

2. Я не понимаю, что вы подразумеваете под «Потому что в первый раз протестируйте nextUrlIndex = 0 , но после …»

3. Спасибо тейлоркресси. Но что вы думаете о главном вопросе 😉

4. Чтобы протестировать метод, вам нужна спецификация для этого метода: тест сравнивает фактическое поведение метода с указанным поведением. Таким образом, никто не может сказать вам, как протестировать ваш метод, если вы не предоставите нам спецификацию для вашего метода.

5. Извините, ребята, я отредактировал приведенный выше код. Это правильный код. Перед первым запуском индекс равен нулю, но, например, если вы запускаете метод во второй или третий раз, индекс не равен 0, он меняется в блоке finally

Ответ №1:

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

Комментарии:

1. Привет, Пелит, я меняю код, чтобы теперь вы могли видеть весь класс.

2. Я сделал это, но тестовый класс может просто протестировать «case VALUE_3: «, когда индекс равен 0. Но как насчет того, когда индекс изменится, и я хочу протестировать его снова?

Ответ №2:

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

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

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

 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