代码之家  ›  专栏  ›  技术社区  ›  Gabriel Ščerbák

如何在参数化测试中测试异常?

  •  12
  • Gabriel Ščerbák  · 技术社区  · 14 年前

    在JUnit4中,可以通过在一个方法中提供参数集合来编写参数化的单元测试,这些参数集合将传递给测试的构造函数,并在另一个方法中进行测试。如果我有一个希望引发异常的参数,该如何指定?

    6 回复  |  直到 9 年前
        1
  •  5
  •   Benoit Courtine    14 年前
    if (parameter == EXCEPTION_EXPECTED) {
        try {
            method(parameter);
            fail("didn't throw an exception!");
        } catch (ExpectedException ee) {
            // Test succeded!
        }
    }
    
        2
  •  28
  •   Yarix    9 年前

    这就是我如何使用junit参数化测试来处理预期的异常:

    @RunWith(Parameterized.class)
    public class CalcDivTest {
    
    @Parameter(0)
    public int num1;
    @Parameter(1)
    public int num2;
    
    @Parameter(2)
    public int expectedResult;
    
    @Parameter(3)
    public Class<? extends Exception> expectedException;
    @Parameter(4)
    public String expectedExceptionMsg;
    
    @Rule
    public ExpectedException thrown = ExpectedException.none();
    
    @Parameters
    public static Iterable<Object[]> data() {
        return Arrays.asList(new Object[][] {
            // calculation scenarios:
            { 120, 10, 12, null, null }, // simple div  
            { 120, 0, -1, ArithmeticException.class, "/ by zero" }, // div by zero          
        });
    
    }
    
    @Test
    public void testDiv() throws CCalculationException {
    
        //setup expected exception
        if (expectedException != null) {
            thrown.expect(expectedException);
            thrown.expectMessage(expectedExceptionMsg);
        }
    
        assertEquals("calculation result is not as", expectedResult, div(num1, num2) );
    
    }
    
    private int div(int a, int b) {
        return a/b;
    }
    }
    
        3
  •  7
  •   Tomek Kaczanowski    12 年前

    与其他建议相反,我不会在测试中引入任何类型的逻辑——即使是简单的ifs!

    你应该有两种测试方法:

    • 第一个接受有效的参数(并期望一些输出)
    • 第二个接受无效参数(并期望出现异常)

    不确定JUnit及其基于构造函数的参数化测试是否能够做到这一点。可能需要为此创建两个测试类。使用JUnit Params或TestNG,它们提供了更方便的解决方案。

        4
  •  3
  •   SoCal    6 年前

    我同意托马克的观点,我会做两个测试。对于不需要异常的情况的第一个测试。对应该导致抛出异常的值的第二次测试(即,如果没有抛出异常,则测试失败)。

    下面是一个简单的示例,其中 ExceptionRower.throwAnInstanceException(int)异常 简单地抛出一个 非法数据异常 当提供的int小于-1时。在您的实现中,所有提供的值都应触发异常。

    @ParameterizedTest
    @ValueSource(ints = {0, 1})
    public void parameterizedIntExceptionTest(int testValue) {
        ExceptionThrower exceptionThrower = new ExceptionThrower();
    
        assertThrows(IllegalArgumentException.class, () -> {
            exceptionThrower.throwAnInstanceException(testValue);
        });
    }
    

    如果你想提供多个参数,那么你可以使用 方法源 恶习a 价值源 为了测试。

        5
  •  1
  •   Noumenon    9 年前

    加布里埃尔,请看看TestWatcher规则(从JUnit4.9开始)。以下是引用的示例代码 http://junit-team.github.io/junit/javadoc/4.11/org/junit/rules/TestWatcher.html :

    public static class WatchmanTest {
        private static String watchedLog;
    
        @Rule
        public TestWatcher watchman= new TestWatcher() {
            @Override
            protected void failed(Throwable e, Description description) {
                watchedLog+= description + "\n";
            }
    
            @Override
            protected void succeeded(Description description) {
                watchedLog+= description + " " + "success!\n";
            }
         };
    
    
         @Test
         public void fails() {
             fail();
         }
    
         @Test
         public void succeeds() {
         }
     }
    

    另一种方法是 ErrorCollector 来自JUnit 4.7: @规则 public ExpectedException throwd=ExpectedException.none();

    @Test
    public void testCollectingErrors() {
        thrown.handleAssertionErrors();
        thrown.expect(MultipleFailureException.class); // or #expectMessage()/#expectCause()
    
        collector.checkThat("a", equalTo("b"));
        //...
    }
    
        6
  •  0
  •   rwitzel    12 年前

    如果你用 catch-exception 与JUnit4的相应注释和规则不同,您的代码如下所示:

    catchException(obj).method(parameter);
    
    if (parameter != EXCEPTION_EXPECTED) {
        assert caughtException() instanceof ExpectedException;
    }
    // more assertions