2013-12-16 22 views
9

Ben iyi belirtilen arayüze sahip ve buna karşı benim JUnit testleri yazmak:Bir test yönteminde çoklu atılan istisnaları test edebilir miyim?

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

[...] 

} 

Eğer uygulama Testleri yazmak zorunda olduğu için çeşitli istisnalar atabilir görebileceğiniz gibi. Ben arabirimde tanımlanan bu bir yöntem için test yöntemlerinin bir sürü tanımlamak zorunda ve hissediyor Yani şimdilik

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

[...] 

} 

: My mevcut yaklaşımın böyle arayüzde belirtilen olası bir istisna için bir test yöntemi yazmaktır garip. Tüm bu istisna testlerini bir test yönteminde birleştirebilir miyim veya en iyi uygulama hangisidir?

cevap

4

Maalesef @Test açıklama birden istisna türü (API referans http://junit.sourceforge.net/javadoc/org/junit/Test.html) yakalamak için izin vermiyor olabilir. İlk seçenek olarak, TestNG'ye geçiş yapmayı savunurdum. Ekibiniz buna izin vermezse, JUnit'te yapabileceğiniz birkaç şey vardır.

Parametreli test durumlarını kesinlikle kullanın, böylece her bir test durumu için bir test fonksiyonu yazmak zorunda kalmazsınız (http://junit.sourceforge.net/javadoc/org/junit/runners/Parameterized.html). Buradan birkaç seçenek var.

  1. Test verilerinizi özel durum türlerine göre gruplayın.

    @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. İstisna türlerini, yöntem imzanızda birleştirin.

    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. şemsiye İstisna sınıfının altında testlerin her koyun ... aşağıda Kaba taslak (Bu tavsiye budur) (Bence bunu yapmak istemediğiniz bir his var.).

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

Bu iyidir, ama sen ExpectedException kuralını kullanarak bu iyileştirebilir: https://github.com/junit-team/junit/blob/master/src/main/java/org/junit /rules/ExpectedException.java –

0

Onları tek bir yöntemle birleştirmek en iyi fikir olmayabilir, çünkü hangi test vakasının hangi istisna yaptığını gerçekten bilmezsiniz. Örneğin

, sen çizgiyi bir NullPointerException atarsam

messageService.createMessage(username, null, topic); 

vardı, ama bunun yerine bir IllegalArgumentException attı eğer, bunu bir başarı olarak saymak istemiyorum.

Bu yöntemin tüm özel durumlarını bir test durumunda test etmek isterseniz, her bir istisna testini try..catch bloğuna sarmak iyi bir alternatif olacaktır.

Örneğin,

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

    // ... 
} 
İlgili konular