Как вы утверждаете, что определенное исключение выбрано в тестах JUnit 4?

Как я могу использовать JUnit4 идиоматически, чтобы проверить, что какой-то код генерирует исключение?

Хотя я могу, конечно, сделать что-то вроде этого:

@Test
public void testFooThrowsIndexOutOfBoundsException() {
  boolean thrown = false;

  try {
    foo.doStuff();
  } catch (IndexOutOfBoundsException e) {
    thrown = true;
  }

  assertTrue(thrown);
}

Я помню, что есть аннотация или Assert.xyz или что-то, что намного меньше kludgy и намного больше в духе JUnit для таких ситуаций.

Ответ 1

JUnit 4 поддерживает это:

@Test(expected = IndexOutOfBoundsException.class)
public void testIndexOutOfBoundsException() {

    ArrayList emptyList = new ArrayList();
    Object o = emptyList.get(0);

}

Ссылка:

Ответ 2

Изменить Теперь, когда 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()

Подробнее см. в этой статье

Ответ 3

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

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

try {
    methodThatShouldThrow();
    fail( "My method didn't throw when I expected it to" );
} catch (MyException expectedException) {
}

Применить решение.

Ответ 4

Как уже было сказано, существует много способов устранения исключений в 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

Раскрытие информации: Я являюсь автором блога и проекта.

Ответ 5

в junit есть четыре способа проверки исключения.

junit5.x

  • для junit5.x вы можете использовать assertThrows следующим образом

    @Test
    public void testFooThrowsIndexOutOfBoundsException() {
        Throwable exception = assertThrows(IndexOutOfBoundsException.class, () -> foo.doStuff());
        assertEquals("expected messages", exception.getMessage());
    }
    

junit4.x

  • для 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.
        }
    }
    
  • так

    • если вам нравится junit 5, то вам должен понравиться первый
    • 2-й способ используется, когда вы хотите проверить только тип исключения
    • первые и последние два используются, когда вы хотите, чтобы тестовое сообщение об исключении было дальше
    • если вы используете junit 3, то четвертый предпочтительнее
  • Для получения дополнительной информации вы можете прочитать этот документ и руководство пользователя junit5 для получения подробной информации.

Ответ 6

ТЛ; др

  • pre-JDK8: Я буду рекомендовать старый хороший блок try - catch. (Не забудьте добавить утверждение fail() перед блоком catch)

  • post-JDK8: используйте AssertJ или пользовательские лямбды, чтобы утверждать исключительное поведение.

Независимо от Junit 4 или JUnit 5.

длинная история

Можно написать сам, сделай сам, try - catch блок или используй инструменты JUnit (@Test(expected =...) или @Rule ExpectedException правила JUnit @Rule ExpectedException).

Но эти способы не так элегантны и не очень хорошо сочетаются с другими инструментами. Кроме того, инструменты JUnit имеют некоторые подводные камни.

  1. В блоке try - catch вы должны написать блок вокруг тестируемого поведения и записать утверждение в блоке catch, что может быть хорошо, но многие считают, что этот стиль прерывает поток чтения теста. Также вам нужно написать Assert.fail в конце блока try иначе тест может пропустить одну сторону утверждений; PMD, findbugs или Sonar обнаружат такие проблемы.

  2. Функция @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
      }
      
  3. Правило 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, потому что в этом случае важен порядок правил.

Таким образом, эти вышеупомянутые опции имеют всю их нагрузку и явно не защищены от ошибок кодера.

  1. Там проект, о котором я узнал после создания этого ответа, выглядит многообещающе, это ловушка-исключение.

    Как говорится в описании проекта, он позволяет кодировщику писать в беглой строке кода, перехватывающей исключение, и предлагает это исключение для последующего утверждения. И вы можете использовать любую библиотеку утверждений, такую как 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, поскольку он предлагает больше, чем просто утверждение исключений.

  2. С 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");
    }
    
  3. С почти полным переписыванием 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 даже если они чувствуют себя неуклюже.

Этот ответ был скопирован с другого вопроса, который не имеет такой же видимости, я тот же автор.

Ответ 7

Теперь, когда 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!");
  }
}

Преимущества в подходах в других ответах:

  • Встроенный JUnit
  • Вы получаете полезное сообщение об исключении, если код в лямбда не генерирует исключение, а stacktrace, если он выдает другое исключение.
  • Сжатый
  • Позволяет вашим тестам следовать Arrange-Act-Assert
  • Вы можете точно указать, какой код вы собираетесь генерировать исключение.
  • Вам не нужно указывать ожидаемое исключение в предложении throws
  • Вы можете использовать структуру утверждений по своему выбору, чтобы делать утверждения об исключении catch

Аналогичный метод будет добавлен в org.junit Assert в JUnit 4.13.

Ответ 8

Как насчет этого: поймайте очень общее исключение, убедитесь, что оно вышло из блока catch, а затем утверждают, что класс исключения - это то, что вы ожидаете от него. Это утверждение будет терпеть неудачу, если: а) исключение будет неправильного типа (например, если вы указали нулевой указатель) и b) исключение никогда не было брошено.

public void testFooThrowsIndexOutOfBoundsException() {
  Throwable e = null;

  try {
    foo.doStuff();
  } catch (Throwable ex) {
    e = ex;
  }

  assertTrue(e instanceof IndexOutOfBoundsException);
}

Ответ 9

BDD Стиль решения: JUnit 4 + Catch Exception + AssertJ

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

Ответ 10

Используя 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");

Maven/ Gradle здесь.

Ответ 11

Чтобы решить ту же проблему, я создал небольшой проект: http://code.google.com/p/catch-exception/

Используя этот маленький помощник, вы должны написать

verifyException(foo, IndexOutOfBoundsException.class).doStuff();

Это менее подробный, чем правило ExpectedException для JUnit 4.7. По сравнению с решением, предоставляемым skaffman, вы можете указать, в какой строке кода вы ожидаете исключения. Надеюсь, это поможет.

Ответ 12

Обновление: 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.

Ответ 13

Вы также можете сделать это:

@Test
public void testFooThrowsIndexOutOfBoundsException() {
    try {
        foo.doStuff();
        assert false;
    } catch (IndexOutOfBoundsException e) {
        assert true;
    }
}

Ответ 14

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"); может быть предпочтительнее.

Ответ 15

Решение JUnit 5

@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

Ответ 16

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

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; и отлично работает с окончательными классами.

Ответ 17

Самый гибкий и элегантный ответ для 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("");

    }

}

Ответ 18

Решение Java 8

Если вы хотите получить решение, которое:

  • Использует Java 8 lambdas
  • Не зависит от какой-либо магии JUnit
  • Позволяет проверять несколько исключений в рамках одного метода тестирования
  • Проверяет, что исключение выбрано определенным набором строк в вашем тестовом методе вместо любой неизвестной строки во всем методе тестирования.
  • Устанавливает фактический объект исключения, который был брошен, чтобы вы могли его изучить.

Вот служебная функция, которую я написал:

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!" );
}

Ответ 19

JUnit имеет встроенную поддержку для этого, с атрибутом "ожидаемый"

Ответ 20

В моем случае я всегда получаю 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));
}

Ответ 21

Просто сделайте Матчи, который можно отключить и включить, например:

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();

Ответ 22

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

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());
}

Ответ 23

В 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");
    }

}

Ответ 24

Кроме того, что сказал NamShubWriter, убедитесь, что:

  • Экземпляр ExpectedException общедоступный (Связанный вопрос)
  • ExpectedException не является, созданным, например, методом @Before. Этот post четко объясняет все тонкости исполнения JUnit.

Сделайте не:

@Rule    
public ExpectedException expectedException;

@Before
public void setup()
{
    expectedException = ExpectedException.none();
}

Наконец, это в блоге ясно показывает, как утверждать, что выбрано какое-то исключение.

Ответ 25

Я рекомендую библиотеку 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(".......);

Ответ 26

Решение 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).

Ответ 27

Возьмем, к примеру, вы хотите написать 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"});
}

Ответ 28

С помощью 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);

Преимущества:

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

Ответ 29

Мое решение с использованием 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);

Ответ 30

Существует два способа написания тестового примера

  • Аннотировать тест с исключением, которое выбрано методом. Что-то вроде этого @Test(expected = IndexOutOfBoundsException.class)
  • Вы можете просто поймать исключение в тестовом классе, используя блок catch try и утвердить сообщение, которое выбрано из метода в тестовом классе.

    try{
    }
    catch(exception to be thrown from method e)
    {
         assertEquals("message", e.getmessage());
    }
    

Я надеюсь, что это ответит на ваш запрос Счастливое обучение...