2013-12-16 3 views
9

は、私にはよく指定されたインターフェイスを持っており、それに対して私は私のJUnitテストを書く:1つのテストメソッドで複数のスローされた例外をテストできますか?

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

[...] 

} 

あなたは実装が、私がテストを書くために持っているため、さまざまな例外をスローすることができます見ることができるように。今、私はインターフェイスで定義された1つの方法のための試験方法の多くを定義する必要があり、それは感じているためだから

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

[...] 

} 

:私の現在のアプローチは、このようなインターフェイスに指定された一つの可能​​な例外の一つの試験方法を書くことです厄介です。これらの例外テストをすべて1つのテスト方法で組み合わせたり、ベストプラクティスを組み合わせることはできますか?

答えて

4

は残念ながら、@Testアノテーションは、複数の例外タイプ(APIリファレンスhttp://junit.sourceforge.net/javadoc/org/junit/Test.html)をキャッチすることができません可能性があります。

最初のオプションとして、私はTestNGへの移行を提唱します。チームがそれを許可しない場合、JUnitでできることはほとんどありません。

テストケースごとに1つのテスト関数(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. (私はあなたがそれを行うにはしたくない気持ちを持っています。)。

    @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

いずれのテストケースが例外を投げたか分からないので、それらをすべて1つの方法で組み合わせることは、最良の考えではないかもしれません。例えば

、あなたがラインNullPointerExceptionスローする必要があり

messageService.createMessage(username, null, topic); 

を持っていたが、その代わりに、それは IllegalArgumentExceptionを投げた場合、あなたはそれが成功としてカウントする必要はありません。

そのメソッドのすべての例外を1つのテストケースでテストする場合は、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(); 
    } 

    // ... 
} 
関連する問題