2015-11-01 43 views
0

JUnit的4.12如何測試引發異常的任何方法調用?

我有以下實用方法:

public class StaticFieldsUtils { 

    public static <T> T getPublicStaticFieldByName(String name, Class<T> clazz){ 
     for(Field f : clazz.getDeclaredFields()){ 
      if(Modifier.isStatic(f.getModifiers()) && 
       Modifier.isPublic(f.getModifiers()) && 
       f.getName().equals(name)) 
       try { 
        Object fieldValue = f.get(null); 
        if(clazz.isAssignableFrom(fieldValue.getClass())) 
         return (T) fieldValue; 
       } catch (IllegalAccessException e) { 
        throw new IllegalArgumentException(String.format("Invalid access to the field %s", name)); 
       } 
     } 
     throw new IllegalArgumentException(String.format("A public field with the name %s does not exist in the class %s", name, clazz.getSimpleName())); 
    } 

    //Some other utility methods 
} 

現在,我需要編寫測試案例,檢查了IllegalArgumetnException拋出只有當有相同類型的任何公共靜態字段或它的一個亞型。

這是我傾向於寫:

public class StaticFieldsUtilsTest { 

    private static class StaticFieldContainer{ 
     public static final StaticFieldContainer FIELD1 = new StaticFieldContainer(); 
     public static final StaticFieldContainer FIELD2 = new StaticFieldContainer(); 
     public static final StaticFieldContainer FIELD3 = new StaticFieldContainer(); 
     public static final StaticFieldContainer FIELD4 = new StaticFieldContainer(); 
     protected static final StaticFieldContainer FIELD5 = new StaticFieldContainer(); 
     static final StaticFieldContainer FIELD6 = new StaticFieldContainer(); 
     private static final StaticFieldContainer FIELD7 = new StaticFieldContainer(); 
     public static StaticFieldContainer FIELD8 = new StaticFieldContainer(); 
    } 

    @Test(expected=IllegalArgumentException.class) 
    public void testViolations(){ 
     StaticFieldContainer field = StaticFieldsUtils.getPublicStaticFieldByName("FIELD5", StaticFieldContainer.class); 
    } 

    @Test(expected=IllegalArgumentException.class) 
    public void testViolations2(){ 
     StaticFieldContainer field = StaticFieldsUtils.getPublicStaticFieldByName("FIELD6", StaticFieldContainer.class); 
    } 
    //ETC 
} 

的問題是我不能可靠地把一個以上的方法調用的一個方法@Test(expected=IllegalArgumentException.class) public void testViolationsX(),因爲我需要檢查每個調用拋出。

問題:有一些JUnit factility避免編寫一個方法任何這樣的調用來檢查它是否拋出?

+1

你要測試什麼?你的utils類還是StaticFieldContainer?如果它是第一個,那麼第二個測試已經過時。 – Tom

+0

@Tom嗯,我認爲StaticFieldContainer是Test類的'private static class'使得它清楚地表明它僅僅用於測試utils類。你難道不明白它爲什麼過時嗎? –

+0

爲什麼你認爲你需要兩次測試這個特定的功能?你擔心第一次測試可能通過運氣嗎?如果你想測試你的類是否也可以讀取包私有變量,那麼你需要使用更好的測試方法名稱在第二種方法中測試它。 – Tom

回答

2

使用JUnit TheoriesExpectedException規則:

@RunWith(Theories.class) 
public class StaticFieldsUtilsTest { 

    //your inner class with static fields 


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

    @DataPoint 
    public static String FIELD1 = "Field1"; 
    @DataPoint 
    public static String FIELD2 = "Field2"; 

    @Theory 
    public void testViolations(String field){ 
    thrown.expect(IllegalArgumentException.class); 
    StaticFieldsUtils.getPublicStaticFieldByName(field, StaticFieldContainer.class); 
    } 
} 

如果你想用其他名字申請的許多理論,我建議創建一個自定義註釋和ParameterSupplier作爲解釋here

+0

非常感謝,有趣的一點。如果測試類包含一個簡單的'@ Test'方法,它可以正常工作嗎?我的意思是,用註解'@RunWith(Theories.class)'標記它沒有任何作用,不是嗎? –

+0

我會將批次和單個測試彼此分開。如果你堅持在一個班級中使用'@ Test'和'@ Theory'而不是嘗試並報告成功或失敗。 – CoronA

+0

試過,因爲我的simeple類包含以下測試方法:'@Test public void test()'然後去'@Theory public void testFieldByNameViolations(String fieldName)'然後'@Theory public void testFieldByNameViolations(StaticFieldContainer staticField)它工作得很好。 –

2

可以使用也可以使用普通的舊式for循環:

public void testViolations(){ 
    for (String fieldName : Arrays.asList("FIELD5", "FIELD6")) { 
     try { 
      StaticFieldContainer field = StaticFieldsUtils.getPublicStaticFieldByName(fieldName, StaticFieldContainer.class); 
      fail(); 
     } catch (IllegalArgumentException e) { 
     } 
    } 
} 
相關問題