2016-03-06 7 views
9

Ich habe einige JUnit (4.12) -Test mit der ExpectedException-Funktion eingerichtet, und ich möchte den Test nach der erwarteten Ausnahme fortsetzen. Aber ich sehe nie das Protokoll '3', da die Ausführung nach der Ausnahme zu stoppen scheint.Wie wird der Test nach JUnit ExpectedException fortgesetzt, wenn er ausgelöst wird?

Ist das tatsächlich möglich, und wie?

@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

möchten Sie möglicherweise einen solchen Test erneut schreiben, wenn Sie nach dem Auslösen einer Ausnahme etwas ausführen möchten. Wenn Sie etwas anderes testen möchten, sollten Sie sie in zwei verschiedene Tests aufteilen, einen, der die Ausnahme prüft und einen zweiten, der die andere Logik überprüft. –

+1

Mögliche Duplikate von [JUnit weiterhin Dinge nach der erwarteten Ausnahme behaupten] (http://stackoverflow.com/questions/21506079/junit-continue-to-assert-things-after-expected-exception) – Joe

Antwort

5

Sie das nicht können, wenn die Ausnahme es ExpectedException Regel für real, geworfen wird geworfen wird oder nicht.

Wenn Sie wirklich diese Art von Verhalten möchten, können Sie auf der „alten Schule“ Muster zurück:

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

log.info("3"); 

Aber ich würde für einige log nicht gestört.

+0

OK, bestätigen Sie, was ich dachte, kein möglicher Weg damit. Vielleicht ist mein Ansatz nicht der beste, wie @thepacker beschreibt. – Deathtiny

2

Diese SO Lösung scheint zu tun, was Sie tun möchten: JUnit continue to assert things after expected exception

ich mich dachte, etwas Ähnliches. Um mit dem Test fortzufahren, müssten Sie die Ausnahme selbst im Test abfangen. Diese Lösung zeigt eine elegante Art, dies zu tun.

Hinweis: Wenn Sie eine Regel erstellen, die (wie Sie) eine Ausnahme erwartet, wird der Test erfolgreich ausgeführt, sobald diese Ausnahme ausgelöst wird. Referenz: http://junit.org/javadoc/latest/org/junit/rules/ExpectedException.html

1

Zunächst einmal testet Ihr Test nicht eine Sache. Es testet "userExists" und "createUser" unter verschiedenen Bedingungen und unter verschiedenen Szenarien. Dies wird AssertionRoulette genannt. Sie würden keinen Hack brauchen, um weiter "3" zu loggen, wenn Sie Tests schreiben würden, die nicht den richtigen Grund haben.

Wenn die Tests aus dem richtigen Grund fehlschlagen, können Sie das Szenario sehen, warum es fehlschlägt, ohne alle Protokollierungsaufgaben zu erledigen. Der Junit-Runner erledigt das Logging für Sie bereits.

@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

Da der UserService eine MongoDB verwendet, besteht das Problem bei diesem Ansatz darin, dass eine Testmethode bereits Daten initialisiert (createUser) und der andere Test fehlschlägt. Oder sollte ich die DB nach jeder Testmethode löschen? – Deathtiny

+0

Sie könnten eine Regel erstellen, die für jeden Test eine Nonce erstellt und eine kleine Servicefunktion erstellt, die einen eindeutigen Namen erstellt. Anstelle von "toto1" wird es "YzFAE4qd_toto1".Sie haben einfach verschiedene Benutzer für jeden Test. Ich habe diesen Ansatz vor nicht allzu langer Zeit gesehen - aber ich weiß nicht mehr wo. Füge das zu meiner Antwort hinzu, wenn ich die Referenz wieder finde. – thepacker

+0

Sie können die Datenbank löschen, nachdem die Klasse bereit ist. @ BeforeClass und @ AfterClass, wenn es nötig ist, aber eine Regel könnte auch die Benutzer bereinigen. Es gibt zu viele Möglichkeiten. – thepacker

1

Wenn Sie nicht wollen, eine Menge von ähnlichen Prüfverfahren für etwas hinzufügen, dass viele Optionen hat die erwartete Ausnahme zu werfen und wollen, um zu überprüfen, dass es wirft tatsächlich auf alle der gewünschten Fälle innerhalb eines Einheit-Test statt, würde ich vorschlagen, diese (nicht ziemlich vielleicht) hilfreich Schema:

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

Das könnte man auch Elemente iterieren (und sogar Funktionen ausführen) einige zuvor vorbereitet Liste anstelle von Schalter-Fall mit harten -kodierte Ganzzahlen.

Verwandte Themen