Как проверить исключение в Java Junit

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

public void validateState(String number){
    if(!number.matches("^M{0,4}(CM|CD|D?C{0,3})(XC|XL|L?X{0,3})(IX|IV|V?I{0,3})$"))
        throw new IllegalArgumentException("Invalid number");

    System.out.println("Invalid number");
}

Контрольная работа:

@Test(expected = IllegalArgumentException.class)
public void test15() throws Exception {
    new RomanNumber("").validateState("MMMMM");
}

Спасибо вам за помощь.


person InExperience    schedule 02.08.2016    source источник
comment
Используйте отладчик, чтобы узнать это   -  person Jens    schedule 02.08.2016
comment
Вероятно, он находится в вашем REGEX, проверьте правильность регулярного выражения   -  person Adelin    schedule 02.08.2016
comment
Небольшое предложение, номер имени переменной, который является строкой, может привести к потенциальной путанице.   -  person Dylan Meeus    schedule 02.08.2016
comment
Тест работает так, как ожидалось: если возникает исключение, тест проходит. демонстрация   -  person BackSlash    schedule 02.08.2016


Ответы (3)


Если тест пройден, это будет означать, что в вашем методе выбрано IllegalArgumentException.
В противном случае тест JUnit завершится неудачно, потому что здесь вы делаете утверждение, что выбрасывается исключение IllegalArgumentException:

@Test(expected = IllegalArgumentException.class)

Удалите @Test(expected = IllegalArgumentException.class), и вы увидите, что тест не прошел.


Отредактируйте, чтобы ответить на свой комментарий: почему я не вижу сообщения "Неверный номер"

Вы видите исключение с трассировкой стека в выводе (терминале), если исключение не обнаружено ни одним вызывающим объектом. Но, как я только что объяснил в своем комментарии, в вашем случае вы не видите исключения, потому что оно перехватывается JUnit (который является вызывающим объектом), поскольку вы использовали ожидаемый атрибут в аннотации @Test. Когда вы запускаете свой метод, бегун JUnit перехватывает ваш брошенный IllegalArgumentException, потому что бегун JUnit знает, что он должен проверить, было ли выброшено IllegalArgumentException.
JVM записывает исключение в вывод (поток ошибок в данном случае), только если исключение возвращается до вершины стека вызовов (это означает, что никто в исполняемом коде не поймал исключение)

person davidxxx    schedule 02.08.2016
comment
Это нормально, что я не вижу сообщения Неверный номер? - person InExperience; 02.08.2016
comment
@ user1526278 Как вы могли увидеть что-то, что написано после оператора, который вызывает исключение и завершает выполнение? У вас должен быть правильный номер - person Krzysztof Cichocki; 02.08.2016
comment
@ user1526278 Это зависит от того, как вы запускаете тесты. Если вы используете eclipse, вы должны увидеть недопустимый номер, щелкнув зеленую полосу выполнения рядом с тестом на вкладке junit. Конечно, отображаемый текст будет сообщением об исключении и трассировкой стека, а не System.out.println после того, как исключение будет выброшено. - person BackSlash; 02.08.2016
comment
@ user1526278 Также не забывайте использовать фигурные скобки. В этом случае ваш оператор печати находится вне оператора if. Вы бы не смогли даже скомпилировать это, если бы оно было внутри. - person BackSlash; 02.08.2016
comment
Вы должны добавить фигурные скобки вокруг двух инструкций и поменять их порядок в обратном порядке, чтобы увидеть сообщение: { System.out.println("Invalid number"); throw new IllegalArgumentException("Invalid number"); } - person davidxxx; 02.08.2016
comment
@davidhxxx: спасибо, Дэвид, за ваше предложение. Теперь я вижу сообщение, но это от System.out.println. Вопрос в том, но если я запускаю исключение, почему я не вижу сообщения IllegalArgumentException (Invalid number)? - person InExperience; 02.08.2016
comment
@InExperience Взгляните на документы JUnit, похоже, вы хотите использовать expectMessage. - person fvu; 02.08.2016
comment
@InExperience где и почему вы хотите увидеть сообщение? В реальном приложении вы должны регистрировать эту информацию с помощью API регистрации. Ваш System.out каким-то образом выполняет эту работу. В вашем случае вы не видите исключения, потому что оно перехвачено JUnit, поскольку вы использовали ожидаемый атрибут в @Test annotation - person davidxxx; 02.08.2016
comment
@davidhxxx: Я думал, что сообщение (Неверный номер) появляется, когда программа генерирует исключение. Как при программировании в терминале. - person InExperience; 02.08.2016
comment
@InExperience слишком много комментариев, я отредактировал свой ответ - person davidxxx; 02.08.2016
comment
@davidhxxx: хорошо, теперь я понимаю почему. Я новичок в подходе к Java и разработке через тестирование (TDD). Спасибо. - person InExperience; 02.08.2016
comment
@InExperience Рад, что вы поняли. Пожалуйста. TDD - отличный подход. Хороший выбор. Я тоже этим занимаюсь. Если я ответил на ваш вопрос, не сомневайтесь, примите мой ответ. - person davidxxx; 02.08.2016

Тест должен пройти, ваша логика верна. Ваш тест говорит, что он ожидает выброса исключения, и это действительно так. Junit перехватывает исключение, проверяет его и выполняет тест.

expected = IllegalArgumentException.class 

Удалите эту строку из аннотации @Test, и она начнет генерировать исключение.

person Adelin    schedule 02.08.2016
comment
Если я удалю @Test (expected = IllegalArgumentException.class), тест будет запущен на других тестовых примерах, и компилятор перескочит на то, что меня интересует. - person InExperience; 02.08.2016
comment
Нет, не удаляйте всю аннотацию, просто ожидайте = IllegalArgumentException.class, если вы хотите видеть ошибки! - person Adelin; 02.08.2016
comment
но мой тестовый код правильный? @Test (expected = IllegalArgumentException.class) public void test15 () выдает исключение {new RomanNumber (). ValidateState (MMMMM); } - person InExperience; 02.08.2016
comment
@ Аделин: конечно. Но я сомневаюсь, почему я не вижу сообщения, которое отправляет IllegalArgumentException? Только этот. Ошибка в тестовом коде? - person InExperience; 02.08.2016

Вы, кажется, спрашиваете, почему

public void validateState(String number) {
    if (!number.matches(...))
        throw new IllegalArgumentException("Invalid number");

    System.out.println("Invalid number");
}

не генерирует исключение И одновременно не выводит сообщение об ошибке.

Причина в том, что при возникновении исключения оно будет распространять операторы пропуска до тех пор, пока исключение не будет перехвачено во включающем try ... catch. В этом случае вызов println будет пропущен. Это нормальное поведение Java ...

Если вы хотите, чтобы исключение было сгенерировано и сообщение было напечатано, напишите это так:

public void validateState(String number) {
    if (!number.matches(...)) {
        System.out.println("Invalid number");
        throw new IllegalArgumentException("Invalid number");
    }
}
person Stephen C    schedule 02.08.2016