2016-03-06 79 views
9

我已經設置了ExpectedException功能的一些JUnit(4.12)測試,我希望測試在預期的異常之後繼續。但是我從來沒有看到日誌'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

1

首先你的測試不測試一件事。它在不同情況下測試「userExists」和「createUser」a.k.a.不同的場景。這被稱爲斷言路由。如果你要編寫測試,那麼你就不需要繼續記錄「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

由於userService在後面使用了MongoDB,這種方法的問題是一個測試方法已經初始化了數據(createUser),另一個測試將失敗。還是應該在每種測試方法後清除數據庫? – Deathtiny

+0

您可以創建一個規則,爲每個測試創建一個隨機數並構建一個小的服務函數,它將創建一個唯一的名稱。而不是「toto1」它將成爲「YzFAE4qd_toto1」。每個測試你都會有不同的用戶。不久前我看到了這種方法 - 但我不記得在哪裏。如果我再次找到參考,將添加到我的答案。 – thepacker

+0

您可以在課程準備就緒後清除數據庫。 @ 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); 
    } 
} 

的人們也可以重複一些預先準備的列表的項目(甚至執行功能),而不是用硬開關情況編碼整數。