Ответ 1
JUnit 4
поддерживает это:
@Test(expected = IndexOutOfBoundsException.class)
public void testIndexOutOfBoundsException() {
ArrayList emptyList = new ArrayList();
Object o = emptyList.get(0);
}
Ссылка:
Как я могу использовать JUnit4 идиоматически, чтобы проверить, что какой-то код генерирует исключение?
Хотя я могу, конечно, сделать что-то вроде этого:
@Test
public void testFooThrowsIndexOutOfBoundsException() {
boolean thrown = false;
try {
foo.doStuff();
} catch (IndexOutOfBoundsException e) {
thrown = true;
}
assertTrue(thrown);
}
Я помню, что есть аннотация или Assert.xyz или что-то, что намного меньше kludgy и намного больше в духе JUnit для таких ситуаций.
JUnit 4
поддерживает это:
@Test(expected = IndexOutOfBoundsException.class)
public void testIndexOutOfBoundsException() {
ArrayList emptyList = new ArrayList();
Object o = emptyList.get(0);
}
Ссылка:
Изменить Теперь, когда JUnit5 выпустил, лучшим вариантом будет использование Assertions.assertThrows()
(см. мой другой ответ).
Если вы не перешли на JUnit 5, но можете использовать JUnit 4.7, вы можете использовать ExpectedException
Правило:
public class FooTest {
@Rule
public final ExpectedException exception = ExpectedException.none();
@Test
public void doStuffThrowsIndexOutOfBoundsException() {
Foo foo = new Foo();
exception.expect(IndexOutOfBoundsException.class);
foo.doStuff();
}
}
Это намного лучше, чем @Test(expected=IndexOutOfBoundsException.class)
, потому что тест потерпит неудачу, если IndexOutOfBoundsException
выбрано до foo.doStuff()
Подробнее см. в этой статье
Будьте осторожны с использованием ожидаемого исключения, потому что он только утверждает, что метод выбрал это исключение, а не конкретную строку кода в тесте.
Я использую это для проверки проверки параметров, потому что такие методы обычно очень просты, но более сложные тесты могут быть лучше:
try {
methodThatShouldThrow();
fail( "My method didn't throw when I expected it to" );
} catch (MyException expectedException) {
}
Применить решение.
Как уже было сказано, существует много способов устранения исключений в JUnit. Но с Java 8 есть еще один: использование Lambda Expressions. С помощью выражений лямбда мы можем добиться синтаксиса следующим образом:
@Test
public void verifiesTypeAndMessage() {
assertThrown(new DummyService()::someMethod)
.isInstanceOf(RuntimeException.class)
.hasMessage("Runtime exception occurred")
.hasMessageStartingWith("Runtime")
.hasMessageEndingWith("occurred")
.hasMessageContaining("exception")
.hasNoCause();
}
assertThrown принимает функциональный интерфейс, экземпляры которого могут быть созданы с помощью лямбда-выражений, ссылок на методы или ссылок на конструкторы. assertThrown, принимающий этот интерфейс, будет ожидать и быть готовым обработать исключение.
Это относительно простая, но мощная техника.
Взгляните на это сообщение в блоге, описывающее эту технику: http://blog.codeleak.pl/2014/07/junit-testing-exception-with-java-8-and-lambda-expressions.html
Исходный код можно найти здесь: https://github.com/kolorobot/unit-testing-demo/tree/master/src/test/java/com/github/kolorobot/exceptions/java8
Раскрытие информации: Я являюсь автором блога и проекта.
в junit есть четыре способа проверки исключения.
для junit5.x вы можете использовать assertThrows
следующим образом
@Test
public void testFooThrowsIndexOutOfBoundsException() {
Throwable exception = assertThrows(IndexOutOfBoundsException.class, () -> foo.doStuff());
assertEquals("expected messages", exception.getMessage());
}
для junit4.x используйте необязательный атрибут "ожидается" аннотации теста
@Test(expected = IndexOutOfBoundsException.class)
public void testFooThrowsIndexOutOfBoundsException() {
foo.doStuff();
}
для junit4.x используйте правило ExpectedException
public class XxxTest {
@Rule
public ExpectedException thrown = ExpectedException.none();
@Test
public void testFooThrowsIndexOutOfBoundsException() {
thrown.expect(IndexOutOfBoundsException.class)
//you can test the exception message like
thrown.expectMessage("expected messages");
foo.doStuff();
}
}
Вы также можете использовать классический способ try/catch, широко используемый в рамках инфраструктуры junit 3
@Test
public void testFooThrowsIndexOutOfBoundsException() {
try {
foo.doStuff();
fail("expected exception was not occured.");
} catch(IndexOutOfBoundsException e) {
//if execution reaches here,
//it indicates this exception was occured.
//so we need not handle it.
}
}
так
Для получения дополнительной информации вы можете прочитать этот документ и руководство пользователя junit5 для получения подробной информации.
ТЛ; др
pre-JDK8: Я буду рекомендовать старый хороший блок try
- catch
. (Не забудьте добавить утверждение fail()
перед блоком catch
)
post-JDK8: используйте AssertJ или пользовательские лямбды, чтобы утверждать исключительное поведение.
Независимо от Junit 4 или JUnit 5.
длинная история
Можно написать сам, сделай сам, try
- catch
блок или используй инструменты JUnit (@Test(expected =...)
или @Rule ExpectedException
правила JUnit @Rule ExpectedException
).
Но эти способы не так элегантны и не очень хорошо сочетаются с другими инструментами. Кроме того, инструменты JUnit имеют некоторые подводные камни.
В блоке try
- catch
вы должны написать блок вокруг тестируемого поведения и записать утверждение в блоке catch, что может быть хорошо, но многие считают, что этот стиль прерывает поток чтения теста. Также вам нужно написать Assert.fail
в конце блока try
иначе тест может пропустить одну сторону утверждений; PMD, findbugs или Sonar обнаружат такие проблемы.
Функция @Test(expected =...)
интересна тем, что вы можете написать меньше кода, и тогда написание этого теста предположительно менее подвержено ошибкам кодирования. Но у этого подхода нет некоторых областей.
Кроме того, поскольку в методе заложено ожидание, в зависимости от того, как написан проверенный код, неправильная часть тестового кода может вызвать исключение, что приведет к ложному положительному тесту, и я не уверен, что PMD, findbugs или Sonar будут давать намеки на такой код.
@Test(expected = WantedException.class)
public void call2_should_throw_a_WantedException__not_call1() {
// init tested
tested.call1(); // may throw a WantedException
// call to be actually tested
tested.call2(); // the call that is supposed to raise an exception
}
Правило ExpectedException
также является попыткой исправить предыдущие предупреждения, но его неудобно использовать, так как он использует стиль ожидания, пользователи EasyMock хорошо знают этот стиль. Для некоторых это может быть удобно, но если вы будете следовать принципам Behavior Driven Development (BDD) или Arrange Act Assert (AAA), правило ExpectedException
не будет соответствовать этому стилю написания. Кроме того, он может страдать от той же проблемы, что и способ @Test
, в зависимости от того, где вы разместили ожидание.
@Rule ExpectedException thrown = ExpectedException.none()
@Test
public void call2_should_throw_a_WantedException__not_call1() {
// expectations
thrown.expect(WantedException.class);
thrown.expectMessage("boom");
// init tested
tested.call1(); // may throw a WantedException
// call to be actually tested
tested.call2(); // the call that is supposed to raise an exception
}
Даже ожидаемое исключение помещается перед оператором теста, оно нарушает ваш поток чтения, если тесты следуют BDD или AAA.
Также см. Этот вопрос комментария на JUnit автора ExpectedException
. JUnit 4.13-beta-2 даже не поддерживает этот механизм:
Запрос на извлечение № 1519: отменить ожидаемое исключение
Метод Assert.assertThrows предоставляет более удобный способ проверки исключений. Кроме того, использование ExpectedException подвержено ошибкам при использовании с другими правилами, такими как TestWatcher, потому что в этом случае важен порядок правил.
Таким образом, эти вышеупомянутые опции имеют всю их нагрузку и явно не защищены от ошибок кодера.
Там проект, о котором я узнал после создания этого ответа, выглядит многообещающе, это ловушка-исключение.
Как говорится в описании проекта, он позволяет кодировщику писать в беглой строке кода, перехватывающей исключение, и предлагает это исключение для последующего утверждения. И вы можете использовать любую библиотеку утверждений, такую как Hamcrest или AssertJ.
Быстрый пример взят с домашней страницы:
// given: an empty list
List myList = new ArrayList();
// when: we try to get the first element of the list
when(myList).get(1);
// then: we expect an IndexOutOfBoundsException
then(caughtException())
.isInstanceOf(IndexOutOfBoundsException.class)
.hasMessage("Index: 1, Size: 0")
.hasNoCause();
Как видите, код действительно прост, вы ловите исключение в определенной строке, then
API-интерфейс - это псевдоним, который будет использовать API-интерфейсы AssertJ (аналогично использованию assertThat(ex).hasNoCause()...
). В какой-то момент проект опирался на FEST-Assert, предка AssertJ. РЕДАКТИРОВАТЬ: Кажется, что проект готовит поддержку Java 8 Lambdas.
В настоящее время эта библиотека имеет два недостатка:
На момент написания этой статьи стоит отметить, что эта библиотека основана на Mockito 1.x, поскольку она создает макет тестируемого объекта за сценой. Поскольку Mockito все еще не обновлен, эта библиотека не может работать с финальными классами или финальными методами. И даже если бы он был основан на mockito 2 в текущей версии, для этого потребовалось бы объявить глобального создателя макетов (inline-mock-maker
), что может не соответствовать вашему желанию, так как этот mockmaker имеет другие недостатки, чем обычный mockmaker.
Требуется еще одна тестовая зависимость.
Эти проблемы не будут применяться, если библиотека будет поддерживать лямбды, однако функциональность будет дублироваться набором инструментов AssertJ.
Принимая все во внимание, если вы не хотите использовать инструмент catch-exception, я порекомендую старый хороший способ блока try
catch
, по крайней мере, до JDK7. А для пользователей JDK 8 вы можете предпочесть использовать AssertJ, поскольку он предлагает больше, чем просто утверждение исключений.
С JDK8 лямбды выходят на тестовую сцену, и они оказались интересным способом заявить об исключительном поведении. AssertJ был обновлен, чтобы обеспечить хороший свободный API для утверждения исключительного поведения.
И пример теста с AssertJ:
@Test
public void test_exception_approach_1() {
...
assertThatExceptionOfType(IOException.class)
.isThrownBy(() -> someBadIOOperation())
.withMessage("boom!");
}
@Test
public void test_exception_approach_2() {
...
assertThatThrownBy(() -> someBadIOOperation())
.isInstanceOf(Exception.class)
.hasMessageContaining("boom");
}
@Test
public void test_exception_approach_3() {
...
// when
Throwable thrown = catchThrowable(() -> someBadIOOperation());
// then
assertThat(thrown).isInstanceOf(Exception.class)
.hasMessageContaining("boom");
}
С почти полным переписыванием JUnit 5 утверждения были немного улучшены, они могут оказаться интересными как готовый способ правильно утверждать исключение. Но на самом деле API утверждений все еще немного беден, за assertThrows
.
@Test
@DisplayName("throws EmptyStackException when peeked")
void throwsExceptionWhenPeeked() {
Throwable t = assertThrows(EmptyStackException.class, () -> stack.peek());
Assertions.assertEquals("...", t.getMessage());
}
Как вы заметили, assertEquals
по-прежнему возвращает void
и поэтому не позволяет объединять утверждения типа AssertJ.
Также, если вы помните коллизия имен с Matcher
или Assert
, будьте готовы встретить такое же коллизия с Assertions
.
Я хотел бы сделать вывод, что сегодня (2017-03-03) простота использования AssertJ, обнаруживаемый API, быстрый темп разработки и фактическая зависимость от тестирования - лучшее решение с JDK8 независимо от среды тестирования (JUnit или нет) предыдущие JDK вместо этого должны полагаться на блоки try
- catch
даже если они чувствуют себя неуклюже.
Этот ответ был скопирован с другого вопроса, который не имеет такой же видимости, я тот же автор.
Теперь, когда JUnit 5 выпустил, лучший вариант - использовать Assertions.assertThrows()
(см.
Руководство пользователя Junit 5).
Вот пример, который проверяет, что генерируется исключение, и использует Truth, чтобы сделать утверждения в сообщении об исключении:
public class FooTest {
@Test
public void doStuffThrowsIndexOutOfBoundsException() {
Foo foo = new Foo();
IndexOutOfBoundsException e = assertThrows(
IndexOutOfBoundsException.class, foo::doStuff);
assertThat(e).hasMessageThat().contains("woops!");
}
}
Преимущества в подходах в других ответах:
throws
Аналогичный метод будет добавлен в org.junit Assert
в JUnit 4.13.
Как насчет этого: поймайте очень общее исключение, убедитесь, что оно вышло из блока catch, а затем утверждают, что класс исключения - это то, что вы ожидаете от него. Это утверждение будет терпеть неудачу, если: а) исключение будет неправильного типа (например, если вы указали нулевой указатель) и b) исключение никогда не было брошено.
public void testFooThrowsIndexOutOfBoundsException() {
Throwable e = null;
try {
foo.doStuff();
} catch (Throwable ex) {
e = ex;
}
assertTrue(e instanceof IndexOutOfBoundsException);
}
import static com.googlecode.catchexception.apis.BDDCatchException.*;
@Test
public void testFooThrowsIndexOutOfBoundsException() {
when(() -> foo.doStuff());
then(caughtException()).isInstanceOf(IndexOutOfBoundsException.class);
}
eu.codearte.catch-exception:catch-exception:2.0
Используя AssertJ утверждение, которое можно использовать рядом с JUnit:
import static org.assertj.core.api.Assertions.*;
@Test
public void testFooThrowsIndexOutOfBoundsException() {
Foo foo = new Foo();
assertThatThrownBy(() -> foo.doStuff())
.isInstanceOf(IndexOutOfBoundsException.class);
}
Это лучше, чем @Test(expected=IndexOutOfBoundsException.class)
, потому что это гарантирует, что ожидаемая строка в тесте бросила исключение и позволит вам более подробно узнать об исключении, таком как сообщение,
assertThatThrownBy(() ->
{
throw new Exception("boom!");
})
.isInstanceOf(Exception.class)
.hasMessageContaining("boom");
Чтобы решить ту же проблему, я создал небольшой проект: http://code.google.com/p/catch-exception/
Используя этот маленький помощник, вы должны написать
verifyException(foo, IndexOutOfBoundsException.class).doStuff();
Это менее подробный, чем правило ExpectedException для JUnit 4.7. По сравнению с решением, предоставляемым skaffman, вы можете указать, в какой строке кода вы ожидаете исключения. Надеюсь, это поможет.
Обновление: JUnit5 улучшает тестирование исключений: assertThrows
.
следующий пример: Руководство пользователя Junit 5
@Test
void exceptionTesting() {
Throwable exception = assertThrows(IllegalArgumentException.class, () ->
{
throw new IllegalArgumentException("a message");
});
assertEquals("a message", exception.getMessage());
}
Оригинальный ответ с использованием JUnit 4.
Существует несколько способов проверки того, что генерируется исключение. Я также обсуждал приведенные ниже варианты в своем сообщении Как написать большие модульные тесты с помощью JUnit
Задайте параметр expected
@Test(expected = FileNotFoundException.class)
.
@Test(expected = FileNotFoundException.class)
public void testReadFile() {
myClass.readFile("test.txt");
}
Используя try
catch
public void testReadFile() {
try {
myClass.readFile("test.txt");
fail("Expected a FileNotFoundException to be thrown");
} catch (FileNotFoundException e) {
assertThat(e.getMessage(), is("The file test.txt does not exist!"));
}
}
Тестирование с помощью правила ExpectedException
.
@Rule
public ExpectedException thrown = ExpectedException.none();
@Test
public void testReadFile() throws FileNotFoundException {
thrown.expect(FileNotFoundException.class);
thrown.expectMessage(startsWith("The file test.txt"));
myClass.readFile("test.txt");
}
Вы можете узнать больше об испытаниях исключений в JUnit4 wiki для тестирования исключений и bad.robot - Ожидание исключений Правило JUnit.
Вы также можете сделать это:
@Test
public void testFooThrowsIndexOutOfBoundsException() {
try {
foo.doStuff();
assert false;
} catch (IndexOutOfBoundsException e) {
assert true;
}
}
IMHO, лучший способ проверить исключения в JUnit - это шаблон try/catch/fail/assert:
// this try block should be as small as possible,
// as you want to make sure you only catch exceptions from your code
try {
sut.doThing();
fail(); // fail if this does not throw any exception
} catch(MyException e) { // only catch the exception you expect,
// otherwise you may catch an exception for a dependency unexpectedly
// a strong assertion on the message,
// in case the exception comes from anywhere an unexpected line of code,
// especially important if your checking IllegalArgumentExceptions
assertEquals("the message I get", e.getMessage());
}
assertTrue
может быть немного сильным для некоторых людей, поэтому assertThat(e.getMessage(), containsString("the message");
может быть предпочтительнее.
@Test
void testFooThrowsIndexOutOfBoundsException() {
Throwable exception = expectThrows( IndexOutOfBoundsException.class, foo::doStuff );
assertEquals( "some message", exception.getMessage() );
}
Дополнительная информация о JUnit 5 на http://junit.org/junit5/docs/current/user-guide/#writing-tests-assertions
Я пробовал многие из методов здесь, но они были либо сложными, либо не совсем отвечали моим требованиям. На самом деле, можно просто написать вспомогательный метод:
public class ExceptionAssertions {
public static void assertException(BlastContainer blastContainer ) {
boolean caughtException = false;
try {
blastContainer.test();
} catch( Exception e ) {
caughtException = true;
}
if( !caughtException ) {
throw new AssertionFailedError("exception expected to be thrown, but was not");
}
}
public static interface BlastContainer {
public void test() throws Exception;
}
}
Используйте его следующим образом:
assertException(new BlastContainer() {
@Override
public void test() throws Exception {
doSomethingThatShouldExceptHere();
}
});
Нулевые зависимости: нет необходимости в mockito, нет необходимости в powerermock; и отлично работает с окончательными классами.
Самый гибкий и элегантный ответ для Junit 4 я нашел в блоге Mkyong. Он имеет гибкость try/catch
с использованием аннотации @Rule
. Мне нравится этот подход, потому что вы можете прочитать определенные атрибуты настроенного исключения.
package com.mkyong;
import com.mkyong.examples.CustomerService;
import com.mkyong.examples.exception.NameNotFoundException;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import static org.hamcrest.CoreMatchers.containsString;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.Matchers.hasProperty;
public class Exception3Test {
@Rule
public ExpectedException thrown = ExpectedException.none();
@Test
public void testNameNotFoundException() throws NameNotFoundException {
//test specific type of exception
thrown.expect(NameNotFoundException.class);
//test message
thrown.expectMessage(is("Name is empty!"));
//test detail
thrown.expect(hasProperty("errCode")); //make sure getters n setters are defined.
thrown.expect(hasProperty("errCode", is(666)));
CustomerService cust = new CustomerService();
cust.findByName("");
}
}
Если вы хотите получить решение, которое:
Вот служебная функция, которую я написал:
public final <T extends Throwable> T expectException( Class<T> exceptionClass, Runnable runnable )
{
try
{
runnable.run();
}
catch( Throwable throwable )
{
if( throwable instanceof AssertionError && throwable.getCause() != null )
throwable = throwable.getCause(); //allows "assert x != null : new IllegalArgumentException();"
assert exceptionClass.isInstance( throwable ) : throwable; //exception of the wrong kind was thrown.
assert throwable.getClass() == exceptionClass : throwable; //exception thrown was a subclass, but not the exact class, expected.
@SuppressWarnings( "unchecked" )
T result = (T)throwable;
return result;
}
assert false; //expected exception was not thrown.
return null; //to keep the compiler happy.
}
Используйте его следующим образом:
@Test
public void testThrows()
{
RuntimeException e = expectException( RuntimeException.class, () ->
{
throw new RuntimeException( "fail!" );
} );
assert e.getMessage().equals( "fail!" );
}
JUnit имеет встроенную поддержку для этого, с атрибутом "ожидаемый"
В моем случае я всегда получаю RuntimeException из db, но сообщения отличаются. И исключение должно обрабатываться соответственно. Вот как я его протестировал:
@Test
public void testThrowsExceptionWhenWrongSku() {
// Given
String articleSimpleSku = "999-999";
int amountOfTransactions = 1;
Exception exception = null;
// When
try {
createNInboundTransactionsForSku(amountOfTransactions, articleSimpleSku);
} catch (RuntimeException e) {
exception = e;
}
// Then
shouldValidateThrowsExceptionWithMessage(exception, MESSAGE_NON_EXISTENT_SKU);
}
private void shouldValidateThrowsExceptionWithMessage(final Exception e, final String message) {
assertNotNull(e);
assertTrue(e.getMessage().contains(message));
}
Просто сделайте Матчи, который можно отключить и включить, например:
public class ExceptionMatcher extends BaseMatcher<Throwable> {
private boolean active = true;
private Class<? extends Throwable> throwable;
public ExceptionMatcher(Class<? extends Throwable> throwable) {
this.throwable = throwable;
}
public void on() {
this.active = true;
}
public void off() {
this.active = false;
}
@Override
public boolean matches(Object object) {
return active && throwable.isAssignableFrom(object.getClass());
}
@Override
public void describeTo(Description description) {
description.appendText("not the covered exception type");
}
}
Чтобы использовать его:
добавить public ExpectedException exception = ExpectedException.none();
,
то:
ExceptionMatcher exMatch = new ExceptionMatcher(MyException.class);
exception.expect(exMatch);
someObject.somethingThatThrowsMyException();
exMatch.off();
Мы можем использовать отказ утверждения после метода, который должен возвращать исключение:
try{
methodThatThrowMyException();
Assert.fail("MyException is not thrown !");
} catch (final Exception exception) {
// Verify if the thrown exception is instance of MyException, otherwise throws an assert failure
assertTrue(exception instanceof MyException, "An exception other than MyException is thrown !");
// In case of verifying the error message
MyException myException = (MyException) exception;
assertEquals("EXPECTED ERROR MESSAGE", myException.getMessage());
}
В JUnit 4 или более поздней версии вы можете протестировать исключения следующим образом
@Rule
public ExpectedException exceptions = ExpectedException.none();
Это дает множество функций, которые могут быть использованы для улучшения наших тестов JUnit.
Если вы видите приведенный ниже пример, я тестирую 3 вещи в исключении.
public class MyTest {
@Rule
public ExpectedException exceptions = ExpectedException.none();
ClassUnderTest classUnderTest;
@Before
public void setUp() throws Exception {
classUnderTest = new ClassUnderTest();
}
@Test
public void testAppleisSweetAndRed() throws Exception {
exceptions.expect(Exception.class);
exceptions.expectMessage("this is the exception message");
exceptions.expectCause(Matchers.<Throwable>equalTo(exceptionCause));
classUnderTest.methodUnderTest("param1", "param2");
}
}
Кроме того, что сказал NamShubWriter, убедитесь, что:
Сделайте не:
@Rule
public ExpectedException expectedException;
@Before
public void setup()
{
expectedException = ExpectedException.none();
}
Наконец, это в блоге ясно показывает, как утверждать, что выбрано какое-то исключение.
Я рекомендую библиотеку assertj-core
обрабатывать исключение в junit test
В java 8, вот так:
//given
//when
Throwable throwable = catchThrowable(() -> anyService.anyMethod(object));
//then
AnyException anyException = (AnyException) throwable;
assertThat(anyException.getMessage()).isEqualTo("........");
assertThat(exception.getCode()).isEqualTo(".......);
Решение Junit4 с Java8 должно использовать эту функцию:
public Throwable assertThrows(Class<? extends Throwable> expectedException, java.util.concurrent.Callable<?> funky) {
try {
funky.call();
} catch (Throwable e) {
if (expectedException.isInstance(e)) {
return e;
}
throw new AssertionError(
String.format("Expected [%s] to be thrown, but was [%s]", expectedException, e));
}
throw new AssertionError(
String.format("Expected [%s] to be thrown, but nothing was thrown.", expectedException));
}
Использование:
assertThrows(ValidationException.class,
() -> finalObject.checkSomething(null));
Обратите внимание, что единственным ограничением является использование ссылки на final
объект в лямбда-выражении. Это решение позволяет продолжить утверждение теста вместо того, чтобы ожидать thowable на уровне метода, используя @Test(expected = IndexOutOfBoundsException.class)
.
Возьмем, к примеру, вы хотите написать Junit для ниже упомянутого фрагмента кода
public int divideByZeroDemo(int a,int b){
return a/b;
}
public void exceptionWithMessage(String [] arr){
throw new ArrayIndexOutOfBoundsException("Array is out of bound");
}
Вышеприведенный код предназначен для проверки какого-либо неизвестного исключения, которое может возникнуть, а нижестоящее - для утверждения некоторого исключения с пользовательским сообщением.
@Rule
public ExpectedException exception=ExpectedException.none();
private Demo demo;
@Before
public void setup(){
demo=new Demo();
}
@Test(expected=ArithmeticException.class)
public void testIfItThrowsAnyException() {
demo.divideByZeroDemo(5, 0);
}
@Test
public void testExceptionWithMessage(){
exception.expectMessage("Array is out of bound");
exception.expect(ArrayIndexOutOfBoundsException.class);
demo.exceptionWithMessage(new String[]{"This","is","a","demo"});
}
С помощью Java 8 вы можете создать метод с кодом для проверки и ожидаемого исключения в качестве параметров:
private void expectException(Runnable r, Class<?> clazz) {
try {
r.run();
fail("Expected: " + clazz.getSimpleName() + " but not thrown");
} catch (Exception e) {
if (!clazz.isInstance(e)) fail("Expected: " + clazz.getSimpleName() + " but " + e.getClass().getSimpleName() + " found", e);
}
}
а затем внутри вашего теста:
expectException(() -> list.sublist(0, 2).get(2), IndexOutOfBoundsException.class);
Преимущества:
Мое решение с использованием Java 8 lambdas:
public static <T extends Throwable> T assertThrows(Class<T> expected, ThrowingRunnable action) throws Throwable {
try {
action.run();
Assert.fail("Did not throw expected " + expected.getSimpleName());
return null; // never actually
} catch (Throwable actual) {
if (!expected.isAssignableFrom(actual.getClass())) { // runtime '!(actual instanceof expected)'
System.err.println("Threw " + actual.getClass().getSimpleName()
+ ", which is not a subtype of expected "
+ expected.getSimpleName());
throw actual; // throw the unexpected Throwable for maximum transparency
} else {
return (T) actual; // return the expected Throwable for further examination
}
}
}
Вы должны определить FunctionalInterface, потому что Runnable
не объявляет требуемый throws
.
@FunctionalInterface
public interface ThrowingRunnable {
void run() throws Throwable;
}
Метод можно использовать следующим образом:
class CustomException extends Exception {
public final String message;
public CustomException(final String message) { this.message = message;}
}
CustomException e = assertThrows(CustomException.class, () -> {
throw new CustomException("Lorem Ipsum");
});
assertEquals("Lorem Ipsum", e.message);
Существует два способа написания тестового примера
@Test(expected = IndexOutOfBoundsException.class)
Вы можете просто поймать исключение в тестовом классе, используя блок catch try и утвердить сообщение, которое выбрано из метода в тестовом классе.
try{
}
catch(exception to be thrown from method e)
{
assertEquals("message", e.getmessage());
}
Я надеюсь, что это ответит на ваш запрос Счастливое обучение...