2011-12-20 46 views
4

我正在测试Xalan使用的WeekConverter并想知道我的测试究竟在做什么。 :dJUnit测试异常期望(多重声明)

具有以下测试方法:

@Test(expected = IllegalArgumentException.class) 
    public void testConvertTwoDigitYearWithWrongInput() { 
    WeekConverter weekConverter = new WeekConverter(WeekConverter.Strategy.TWO_DIGIT_YEAR); 

    //wrong or empty inputs 
    assertEquals("0", weekConverter.convert("")); 
    assertEquals("0", weekConverter.convert("abcdefgh")); 
} 

将这个测试期望对所有异常断言,或者只对第一个断言?如果只有第一个,这意味着我必须为每个断言创建一个测试方法,但我期望在这两种情况下都有相同的异常。有人可以在这里确认我的例子吗?

我也有一个测试null,这会产生一个空指针异常。软验证是以下情况:

if (inputDate == null) { 
    do something and throw NullPointerexception 
} else if (inputDate.isEmpty()) { 
    do something and throw IllegalArgumentException, since inputDate is not really null 
} else if (inputDate.matches(regex)) { 
    go futher and convert 
} else { 
    do something and throw IllegalArgumentException, since inputDate does not match regex 
} 

因此所述一个测试方法期待抛出:IllegalArgumentException具有两个断言。但很显然,我需要两种不同的测试方法,不仅要尊重JUnit的功能,还要期待两种不同的状态。

+0

既然你期待一个例外,你并不需要断言等于 - 所有你需要的是转换的呼叫。 – avandeursen 2011-12-26 21:41:34

回答

3

您可以将您的方法分解为多种方法,但是如果您有很多输入样本,将会很不方便。

您可以用下面的办法来代替:

@Test 
public void testConvertTwoDigitYearWithWrongInput() { 
    WeekConverter weekConverter = new WeekConverter(WeekConverter.Strategy.TWO_DIGIT_YEAR); 

    assertFailsToConvert(weekConverter, ""); 
    assertFailsToConvert(weekConverter, "abcdefgh"); 
} 

private void assertFailsToConvert(WeekConverter weekConverter, String input) { 
    try { 
     weekConverter.convert(input); 
     fail("Should not convert [" + input + "]"); 
    } catch (IllegalArgumentException ex) {} 
} 
+0

这样做的问题在于,如果没有查看测试,测试不再是自我记录,并且不能以没有AST和猜测的人类可读形式记录。保持它们分开允许更好的信息生成。 – 2011-12-20 17:02:22

+0

excactly(评论) – 2011-12-20 17:07:32

+1

但是,针对不同输入样本进行大量单独测试会妨碍可读性和可维护性,因此您应该决定哪些对您更重要。 – axtavt 2011-12-20 17:10:33

1

您应该提供多种测试方法,因为他们正在测试不同的东西。

第一次转换器得到非法参数时将引发异常。

您还应该测试空输入,以便记录行为。

+0

这是一个很好的观点......特别是当抛出相同的异常但来自不同的状态。 – 2011-12-20 16:56:06

1

测试只是期待IllegalArgumentException被抛出,无论从哪里或为什么抛出。

我建议你把它分成两个测试。

1

你可以把转换夹具创建一个单独的@Before设置方法,然后你可以有(三级)测试用例来对付null,“”和“abcdef”。

如果有更多的案例需要测试, 在JUnit中的一个整洁的方法是使用@Parameters注释和相应的跑步者。

你的测试课只处理不正确的两位数的年份。其构造函数将使用String类型的inputDate进行参数化。

产生@Parameters的静态方法将返回包含""abcdefg(以及其他有趣的情况)的集合。

单个测试用例预期为IllegalArgumentException

@RunWith(Parameterized.class) 
public class IncorrectTwoDigitYears { 
    String inputDate; 

    public IncorrectTwoDigitYears(String inputDate) { 
     this.inputDate = inputDate; 
    } 

    @Test(expected = IllegalArgumentException.class) 
    public void testFormat() { 
     (new WeekConverter(WeekConverter.Strategy.TWO_DIGIT_YEAR)) 
      .convert(inputDate); 
    } 

    @Parameters 
    public static Collection<Object[]> data() { 
     Object[][] data = new Object[][] { 
      { "" }, { "abcdef" }, { "0" }, { "000" }, { "##" } }; 
     return Arrays.asList(data); 
    } 
} 

如果您有两个以上的案例需要测试,回报将会更高。

1

尝试catch-exception

@Test 
public void testConvertTwoDigitYearWithWrongInput() { 

    WeekConverter weekConverter = ... 

    // wrong or empty inputs 
    verifyException(weekConverter, IllegalArgumentException.class) 
     .convert(""); 
    verifyException(weekConverter, IllegalArgumentException.class) 
     .convert("abcdefgh"); 
}