2013-05-16 4 views
21

Я написал несколько тестовых примеров для тестирования некоторого метода. Но некоторые методы вызывают исключение. Правильно ли я делаю это?Как обрабатывать исключения в junit

private void testNumber(String word, int number) { 
    try { 
     assertEquals(word, service.convert(number)); 
    } catch (OutOfRangeNumberException e) { 
     Assert.fail("Test failed : " + e.getMessage()); 
    } 
} 

@Test 
public final void testZero() { 
    testNumber("zero", 0); 
} 

Если я прохожу -45, он потерпит неудачу с OutOfRangeException, но я не в состоянии проверить конкретное исключение, как @Test(Expected...)

ответ

6

Вам не нужно, чтобы поймать исключение провалить тест. Просто отпустите его (объявив throws), и он все равно потерпит неудачу.

Другой случай, когда вы действительно ожидаете исключения, тогда вы положите fail в конце блока try.

Например:

@Test 
public void testInvalidNumber() { 
    try { 
     String dummy = service.convert(-1)); 
     Assert.fail("Fail! Method was expected to throw an exception because negative numbers are not supported.") 
    } catch (OutOfRangeException e) { 
     // expected 
    } 
} 

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

+1

ExpectedException является предпочтительным способом проверить ожидаемых исключений. –

+0

Я согласен, и я уже поддержал ответ Эрика. – javadeveloper

+0

Вам нужно только ExpectedException, если вам нужно проверить структуру исключения. Например, предполагается, что в CmisExceptions есть определенная причина сбоя. Я должен был написать тесты, чтобы проверить это, и для этой цели я использовал комбинации Hamcrest. Если вы просто ожидаете исключения, используйте аргумент для @Test. –

15

Удалить блок примерочных поймать и добавить throws Exception к вашему методу испытаний, как:

@Test 
public final void testZero() throws Exception { 
    assertEquals("zero", service.convert(0)); 
} 

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

45

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

@Test 
public void canConvertStringsToDecimals() { 
    String str = "1.234"; 
    Assert.assertEquals(1.234, service.convert(str), 1.0e-4); 
} 

До service не бросаться IllegalArgumentException, потому что str имеет десятичную точку в нем, что будет просто провал теста.

Ожидаемое исключение должно обрабатываться необязательным аргументом expected@Test.

@Test(expected=NullPointerException.class) 
public void cannotConvertNulls() { 
    service.convert(null); 
} 

Если программист поленился и бросил Exception, или если он был service возвращение 0.0, тест проваливается. Только NPE преуспеет. Обратите внимание, что также работают подклассы ожидаемого исключения. Это редкость для NPE s, но распространено с IOException s и SQLException s.

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

@Rule 
public ExpectedException thrown= ExpectedException.none(); 
@Test 
public void messageIncludesErrantTemperature() { 
    thrown.expect(IllegalArgumentException.class); 
    thrown.expectMessage("-400"); // Tests that the message contains -400. 
    temperatureGauge.setTemperature(-400); 
} 

Теперь, если setTemperature не бросает IAE и сообщение содержит температуру пользователь пытался установить, тест не пройден. Это правило может использоваться более сложными способами.


Ваш пример может лучше всего быть обработаны:

private void testNumber(String word, int number) 
     throws OutOfRangeNumberException { 
    assertEquals(word, service.convert(number)); 
} 

@Test 
public final void testZero() 
     throws OutOfRangeNumberException { 
    testNumber("zero", 0); 
} 

Вы можете встраивать testNumber; теперь это мало помогает. Вы можете превратить это в параметризованный тестовый класс.

2

Существует несколько стратегий, которые открыты для вас, чтобы иметь дело с ожидаемыми исключениями в ваших тестах. Я думаю, что аннотации JUnit и идиома try/catch уже упоминались выше. Я хотел бы обратить внимание на вариант Java 8 для лямбда-выражений.

Например Дано:

class DummyService { 
public void someMethod() { 
    throw new RuntimeException("Runtime exception occurred"); 
} 

public void someOtherMethod(boolean b) { 
    throw new RuntimeException("Runtime exception occurred", 
      new IllegalStateException("Illegal state")); 
} 

}

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

@Test 
public void verifiesCauseType() { 
    // lambda expression 
    assertThrown(() -> new DummyService().someOtherMethod(true)) 
      // assertions 
      .isInstanceOf(RuntimeException.class) 
      .hasMessage("Runtime exception occurred") 
      .hasCauseInstanceOf(IllegalStateException.class); 
} 

Посмотрите на этот блог, который охватывает большинство вариантов с примерами.

http://blog.codeleak.pl/2013/07/3-ways-of-handling-exceptions-in-junit.html

И это один объясняет вариант Java 8 Lambda более полно:

http://blog.codeleak.pl/2014/07/junit-testing-exception-with-java-8-and-lambda-expressions.html

Смежные вопросы