2016-03-06 3 views
9

Я установил некоторый тест JUnit (4.12) с функцией ExpectedException, и я хотел бы, чтобы тест продолжался после ожидаемого исключения. Но я никогда не вижу журнал «3», так как выполнение, похоже, прекращается после исключения, событие, если оно уловлено?Как продолжить тест после исключения JUnit ExpectedException при броске?

Возможно ли это, и как?

@Rule 
public ExpectedException exception = ExpectedException.none(); 

@Test 
public void testUserAlreadyExists() throws Exception { 
    log.info("1"); 

    // Create some users 
    userService.createUser("toto1"); 
    userService.createUser("toto2"); 
    userService.createUser("toto3"); 
    Assert.assertTrue(userService.userExists("toto1")); 
    Assert.assertTrue(userService.userExists("toto2")); 
    Assert.assertTrue(userService.userExists("toto3")); 

    log.info("2"); 

    // Try to create an existing user 
    exception.expect(AlreadyExistsException.class); 
    userService.createUser("toto1"); 

    log.info("3"); 
} 
+0

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

+1

Возможный дубликат [JUnit продолжать утверждать вещи после ожидаемого исключения] (http://stackoverflow.com/questions/21506079/junit-continue-to-assert-things-after-expected-exception) – Joe

ответ

5

Вы не можете сделать это, когда исключение это брошено на реальное, ExpectedException правила или нет.

Если вы действительно хотите такого рода поведение, вы можете вернуться к «старой школы» схеме:

try { 
    userService.createUser("toto1"); 
    Assert.fail("expecting some AlreadyExistsException here") 
} catch (AlreadyExistsException e) { 
    // ignore 
} 

log.info("3"); 

Но я бы не стал заморачиваться на какой-то журнал.

+0

Хорошо, вы подтверждаете, что я подумал, с этим не было возможным. Возможно, мой подход не самый лучший, как описывает @ thepacker. – Deathtiny

2

Это решение кажется SO делать то, что вы хотите сделать: JUnit continue to assert things after expected exception

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

Примечание. Если вы делаете правило, чтобы ожидать исключения (как и вы), тест вернется успешно, как только это исключение будет выбрано. Код: http://junit.org/javadoc/latest/org/junit/rules/ExpectedException.html

1

Прежде всего, ваш тест не проверяет одну вещь. Он тестирует «userExists» и «createUser» в разных условиях a.k.a. разных сценариев. Это называется AssertionRoulette. Вам не потребуется взломать, чтобы продолжить запись «3», если вы будете писать тесты, которые не подходят по правильной причине.

Если тесты не удались по правильной причине, вы можете увидеть сценарий, почему он терпит неудачу, не выполняя все записи. Junit-Runner уже регистрирует вас.

@Test 
public void testUserExists_UserCreatedUserNotExistent_expectTrue() 
{ 
    // Create some users 
    userService.createUser("toto1"); 

    // Assert That user exists 
    Assert.assertTrue(userService.userExists("toto1")); 
} 

@Test 
public void testCreateUser_UserAlreadyCreated_expectAlreadyExistsExceptionIsThrown() 
{ 
    // Create some users 
    userService.createUser("toto1"); 

    // Try to create an existing user 
    exception.expect(AlreadyExistsException.class); 
    userService.createUser("toto1");  
} 
+0

Поскольку пользовательский сервис использует MongoDB позади, проблема с этим подходом заключается в том, что один тестовый метод уже инициализирует данные (createUser), а другой тест завершится с ошибкой. Или я должен очистить БД после каждого метода тестирования? – Deathtiny

+0

Вы можете создать правило, которое создаст nonce для каждого теста и построит небольшую сервисную функцию, которая создаст уникальное имя. Вместо «toto1» он станет «YzFAE4qd_toto1».У вас просто будут разные пользователи для каждого теста. Я давно видел этот подход, но я не помню, где. Добавлю это к моему ответу, если снова найду ссылку. – thepacker

+0

Вы можете очистить db после того, как класс будет готов. @ BeforeClass и @ AfterClass, если вам нужно, но правило может также очистить пользователей. Слишком много возможностей. – thepacker

1

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

@Test 
public void testThatSomethingExpectedlyFails() { 
    for (int i = 1; i <= 3; i++) { 
     try { 
      switch (i) { 
       case 1: // smth here throws the exception when configuration #1; 
       case 2: // smth here throws the exception when configuration #2; 
       case 3: // smth here throws the exception when configuration #3; 
      } 
     } catch (ExceptionThatIsExpected expected) { 
      continue; 
     } catch (Exception unexpected) { 
      /* the test must fail when an unexpected exception is thrown */     
      fail("The test has failed due to an unexpected exception: " + unexpected.getMessage()); // or just re-throw this exception 
     } 

     /* the test must fail when a case completes without the expected exception */ 
     fail("No expected exception occurred at case " + i); 
    } 
} 

Тем также может перебирать элементы (и даже выполнять функции) некоторые предварительно подготовленный список вместо переключения регистр с жестким -кодированные целые числа.

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