2013-12-16 85 views
9

我有一個很好指定接口和反對,我寫我的JUnit測試:我可以在一種測試方法中測試多個拋出的異常嗎?

public interface ShortMessageService { 

    /** 
    * Creates a message. A message is related to a topic 
    * Creates a date for the message 
    * @throws IllegalArgumentException, if the message is longer then 255 characters. 
    * @throws IllegalArgumentException, if the message ist shorter then 10 characters. 
    * @throws IllegalArgumentException, if the user doesn't exist 
    * @throws IllegalArgumentException, if the topic doesn't exist 
    * @throws NullPointerException, if one argument is null. 
    * @param userName 
    * @param message 
    * @return ID of the new created message 
    */ 
    Long createMessage(String userName, String message, String topic); 

[...] 

} 

正如你所看到的實施可以拋出,我必須寫測試各種異常。我目前的做法是寫在界面中這樣規定的一個可能的例外是一個測試方法:

public abstract class AbstractShortMessageServiceTest 
{ 

    String message; 
    String username; 
    String topic; 

    /** 
    * @return A new empty instance of an implementation of ShortMessageService. 
    */ 
    protected abstract ShortMessageService getNewShortMessageService(); 

    private ShortMessageService messageService; 

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

    @Before 
    public void setUp() throws Exception 
    { 
     messageService = getNewShortMessageService(); 
     message = "Test Message"; 
     username = "TestUser"; 
     topic = "TestTopic"; 
    } 

    @Test 
    public void testCreateMessage() 
    { 
     assertEquals(new Long(1L), messageService.createMessage(username, message, topic)); 
    } 

    @Test (expected = IllegalArgumentException.class) 
    public void testCreateMessageUserMissing() throws Exception 
    { 
     messageService.createMessage("", message, topic); 
    } 

    @Test (expected = IllegalArgumentException.class) 
    public void testCreateMessageTopicMissing() throws Exception 
    { 
     messageService.createMessage(username, message, ""); 
    } 

    @Test (expected = IllegalArgumentException.class) 
    public void testCreateMessageTooLong() throws Exception 
    { 
     String message = ""; 
     for (int i=0; i<255; i++) { 
      message += "a"; 
     } 
     messageService.createMessage(username, message, topic); 
    } 


    @Test (expected = IllegalArgumentException.class) 
    public void testCreateMessageTooShort() throws Exception 
    { 
     messageService.createMessage(username, "", topic); 
    } 

    @Test (expected = NullPointerException.class) 
    public void testCreateMessageNull() throws Exception 
    { 
     messageService.createMessage(username, null, topic); 
    } 

[...] 

} 

所以現在我必須定義一個很大的試驗方法的接口定義了一個方法和感覺尷尬。我可以將所有這些異常測試結合在一種測試方法中,還是最佳實踐是什麼?

回答

4

不幸的是,@Test標註不允許捕獲多種異常(API參考http://junit.sourceforge.net/javadoc/org/junit/Test.html)。

作爲第一個選擇,我會主張移植到TestNG。如果你的團隊不允許這樣做,那麼在JUnit中你可以做的事情很少。

絕對使用參數化測試用例,因此您不必爲每個測試用例編寫一個測試函數(http://junit.sourceforge.net/javadoc/org/junit/runners/Parameterized.html)。從這裏,有幾個選項。

  1. 按異常類型對測試數據進行分組。

    @Test (expected = IllegalArgumentException.class) 
    public void testIllegalArgumentException(String username, String message, String topic) {} 
    
    @Test (expected = NullPointerException.class) 
    public void testNullPointerException(String username, String message, String topic) {} 
    
  2. 在您的方法簽名中組合異常類型。 (這是我的建議)以下粗線條...

    public void testException(String username, String message, String topic, Class<? extends Exception>[] expectedExceptionClasses) { 
        try { 
         // exception throwing code 
        } catch (Exception e) { 
         boolean found = false; 
         for (Class<?> expectedException : expectedExceptions) { 
          if (e instanceof expectedException) { 
           found = true; 
          } 
         } 
         if (found) { 
          return; 
         } 
        } 
        Assert.fail(); 
    } 
    
  3. 把所有的傘Exception類下進行測試的(我有你不想做的感覺。)。

    @Test (expected = Exception.class) 
    public void testException(String username, String message, String topic) {} 
    
+1

這是一件好事,但你可以使用的ExpectedException規則改善這一點:https://github.com/junit-team/junit/blob/master/src/main/java/org/junit /rules/ExpectedException.java –

0

將它們全部結合在一個方法中可能不是最好的想法,因爲您不知道哪個測試用例拋出了哪個異常。

例如,如果你有行

messageService.createMessage(username, null, topic); 

應該拋出一個NullPointerException,而是拋出了IllegalArgumentException,你不希望出現這種情況計算爲一次成功。

如果您想在一個測試用例中測試該方法的所有異常,那麼一個很好的選擇是將每個異常測試包裝在try..catch塊中。

例如,你可以有

@Test 
public void testCreateMessageExceptions() { 
    // test #1: a null message 
    try { 
     messageService.createMessage(username, null, topic); 
     // if it got this far, that's a problem! 
     fail(); 
    } catch(NullPointerException e) { 
     // great, that's what it's meant to do! continue testing 
    } catch(Exception e) { 
     // if it threw the wrong type of exception, that's a problem! 
     fail(); 
    } 

    // test #2: an empty user 
    try { 
     messageService.createMessage("", message, topic); 
     fail(); 
    } catch(IllegalArgumentException e) { 

    } catch(Exception e) { 
     fail(); 
    } 

    // ... 
} 
相關問題