Подтвердить что ты не робот

Попробуйте поймать тест JUnit

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

public void someMethod() throws Exception { 
   //do something 
}

Если я хочу протестировать эти методы, я должен написать что-то вроде этого в моем unit test:

@Test
public void someTest() {
   try {
      someMethod();
   }
   catch (Exception e) {
      e.printStackTrace();
   }
}

Хорошо ли это? Или есть другой способ проверить эти методы?

Я провел некоторое исследование в Интернете, и я нашел несколько решений с аннотацией @Rule и @Test(expected=Exception.class), но это не работает (Eclipse продолжает показывать строку someMethod() в тесте как ошибочную). Я не знаю, являются ли они хорошими решениями, потому что я довольно новичок во всей истории тестирования модулей.

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

4b9b3361

Ответ 1

Так как Exception является проверенным исключением, вы либо:

  • Устранить исключение в инструкции try...catch или
  • Объявить исключение, которое должно быть выбрано в самом методе.

То, что у вас там хорошо работает, но мое личное предпочтение заключается в том, чтобы объявить исключение. Таким образом, если исключение, которое я не ожидаю, вызывается во время запуска теста, тест завершится с ошибкой.

@Test
public void someTest() throws Exception {
    // dodgy code here
}

Если нам нужно увидеть, возникает ли какое-либо конкретное исключение, вы можете использовать @Rule или добавить значение в аннотацию @Test.

@Test(expected = FileNotFoundException.class)
public void someTest() throws Exception {
    // dodgy code here
}

В JUnit 5 вы можете использовать Assertions.expectThrows, чтобы выполнить одно и то же. Я меньше знаком с этим, так как он еще не был на момент редактирования, но он, кажется, принимает Executable, исходящий из JUnit 5.

@Test
public void someTest() {
    assertThrows(FileNotFoundException.class, () ->
         { dodgyService.breakableMethod() };
}

Ответ 2

@Test
public void someTest() {
   try {
     someMethod();
   }
   catch (Exception e) {
     Assert.fail("Exception " + e);
   }
}

Это то, что вы можете сделать, если исключение не должно происходить. Альтернативой было бы сделать исключение в сигнатуре следующим образом:

@Test
public void someTest() throws Exception {
     someMethod();
}

Разница заключается в том, что в одном случае тест завершится с исключением с утверждением, а в другом случае он потерпит неудачу, потому что тест разбился. (например, где-то в вашем коде вы получаете NPE, и из-за этого будет тест)

Причина, по которой вы должны это сделать, заключается в том, что Exception является проверенным исключением. См. Проверено или исключено исключение

@Test (expected = Exception.class) предназначен для тестов, которые хотят проверить, будет ли выбрано исключение.

@Test(expected=ArrayIndexOutOfBounds.class)
public void testIndex() {
   int[] array = new int[0];
   int var = array[0]; //exception will be thrown here, but test will be green, because we expect this exception

}

Ответ 3

Не проверяйте исключение своего приложения в тестовом коде. Вместо этого объявите его, чтобы он был поднят вверх.

Потому что, когда JUnit TestRunner находит созданное исключение, он автоматически регистрирует его как error для тестового файла.

Только если вы testcase ожидаете, что метод должен был бросить Exception, вы должны использовать @Test(expected=Exception.class) или поймать исключение.

В других случаях просто бросьте его вверх,

public void someTest() throws Exception {

Ответ 4

Вы можете добавить исключение в подпись метода тестирования. Затем, если вы проверяете, выбрано ли исключение, вы должны использовать @Test(expected=Exception.class). В тестовых случаях, когда исключение не нужно бросать, тест пройдет успешно.

@Test
public void testCaseWhereExceptionWontBeThrown() throws Exception {
    someMethod(); //Test pass
}

@Test(expected=Exception.class)
public void testCaseWhereExceptionWillBeThrown() throws Exception {
    someMethod(); //Test pass
}

Ответ 5

Существует два основных правила обработки исключений в тестерах Junit:

  • Если исключение было отправлено в тестируемый код:

    • Если бы это ожидалось, объявите его в атрибуте expected аннотации Test. Или, если дальнейшие проверки должны выполняться самим объектом исключения, поймите его и проигнорируйте. (В этом случае должен быть также вызов Assert.fail в конце блока try, чтобы указать, что ожидаемое исключение не было создано).
    • Если бы этого не ожидалось, поймайте его и выполните Assert.fail. (Предыдущий вызов Exception.printStackTrace также полезен).
  • Если исключение не было создано в тестируемом коде или оно не является интересным для теста (например, большинство IOExceptions создаются на сетевом уровне, прежде чем тест может быть даже завершен), перестройте его на предложение throws.

Почему вы должны ожидать исключения в тесте? Напомним: вы должны набрать один тестовый метод для каждого возможного результата на тестируемом коде (для достижения высокого покрытия кода): в вашем случае один метод, который должен успешно возвратиться, и, по крайней мере, другой, который должен создать исключение.

Ответ 6

Три точки о JUnit:

  • Тесты должны быть точными, они должны проходить или нечетко однозначно основываться исключительно на том, как настроены тестовые входы.

  • Тесты должны иметь ошибки, о которых сообщалось в рамку.

  • Тесты не должны полагаться на чтение своих результатов.

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

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

Если вы ожидаете, что тест будет успешным без исключения исключения, то, если что-либо в тесте может выставить проверенное исключение, добавьте throws Exception в подпись метода тестирования. Добавление throws в подпись не означает, что метод должен что-то бросать, он просто позволяет любые исключения, которые случаются, бросаются так, что тестовая среда может их поймать.

Единственный экземпляр, в котором вы действительно поймаете исключение в тесте, - это то, где вы хотите проверить утверждения об исключении; например, вы можете проверить, что сообщение об исключении - это то, что вы ожидаете, или если на задании причины есть причина. В этом случае вы добавили бы Assert.fail() в конец блока try, чтобы исключение не было вызвано ошибкой.

Когда вы сначала пишете тест, сделайте ошибку. Таким образом, вы сами доказываете, что знаете, что делает тест, и подтверждаете, что когда произойдет сбой, вы узнаете об этом.

Ответ 7

Какое исключение? Это

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

Если это 1. Я бы просто положил его на уровень подписи метода, потому что try-catch не служит никакой реальной цели, кроме церемонии.

@Test
public void testFoo() throws Exception {
    // ...
}

Если он 2., он становится немного более сложным. Вы должны спросить себя, что должно произойти, если исключение исключено. Если тест не пройдет? Ожидается? Это неуместно? Ниже приведены примеры того, как обрабатывать все эти. BEWARE: Я использовал Exception только потому, что вы это сделали. Я надеюсь, что это действительно не так, потому что, если возможно, чтобы какое-то другое исключение было выбрано иначе, чем ожидалось, это будет очень неприятно. Если возможно, не используйте Exception, используйте что-то более конкретное (в junit и code).

// The below code assumes you've imported the org.junit.Assert class.

@Test
public void thisShouldFailIfExceptionCaught() {
    //Given...
    try {
        // When...
    } catch (Exception e) {
        Assert.fail();
    }
    // Then...
}

@Test
public void thisShouldPassOnlyIfTheExceptionIsCaught() {
    //Given...
    try {
        // When...
        Assert.fail();
    } catch (Exception expected) {}
    // No "then" needed, the fact that it didn't fail is enough.
}

@Test
public void irrelevantExceptionThatCouldBeThrown() {
    //Given...
    try {
        // When...
    } catch (Exception e) {}
    // Then...
}