4

I have the following piece of code:

@Test(expected = IllegalArgumentException.class)
public void failureTest()    {
    testedObject.supposedToFail("");
    testedObject.supposedToFail(null);
}

When running this, I have no guarantee that I will throw an IllegalArgumentException with a null parameter. Indeed, whenever JUnit meets the first exception, it stops the run of the whole method.

Considering the number of test cases I have to try for this class (~20), I doubt writing 20 methods each expecting a specific exception (which are often the same, tho) would be efficient.

Is there any way to try for every method throwing a specific exception at once ? (e.g. with my sample, you would go through both methods)

Thank you

4

3 回答 3

2

我会使用一种辅助方法并这样做:

编辑:这不起作用,请参阅替代工作解决方案

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

@Test
public void myTest() {
    List<Object[]> paramsList = Arrays.asList(
        new Object[] {"", IllegalArgumentException.class},
        new Object[] {null, NullPointerException.class});
    paramsList.forEach(a -> assertExceptionForParam((String)a[0], (Class)a[1]));
}

private void assertExceptionForParam(String param, Class expectedExceptionClass) {
    thrown.expect(expectedExceptionClass);
    testedObject.supposedToFail(param);
}

替代工作解决方案,在 MIRZAK 评论后更改

我的解决方案实际上似乎只测试列表中的第一个案例。这是一个可以测试它们的工作版本

@Test
public void myTest() {
    List<Object[]> paramsList = Arrays.asList(
        new Object[] {null, NullPointerException.class},
        new Object[] {"", IllegalArgumentException.class},
        new Object[] {"zip", NullPointerException.class});
    paramsList.forEach(a -> assertExceptionForParam((String)a[0], (Class)a[1]));
}

private void assertExceptionForParam(String param, Class expectedExceptionClass) {
    boolean pass = false;
    try {
        testedObject.supposedToFail(param);
    } catch(Exception e) {
        pass = e.getClass() == expectedExceptionClass;
    }
    Assert.assertTrue("test failed for param:" + param + " and Exception "+expectedExceptionClass, pass);
}

正如预期的那样输出:

java.lang.AssertionError: test failed for param:zip and Exception class java.lang.NullPointerException
于 2018-01-03T11:46:54.830 回答
1

Unfortunately, auxiliary method won't work in that case, because @Test method will pass even if only one of auxiliary method invocations throws exception.

I didn't find a beautiful way to implement such test and end up with something like this:

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

@Test
public void testThrowIllegalArgumentExceptionForEmptyParam() {
    assertExceptionForParam("", IllegalArgumentException.class);
}

@Test
public void testThrowNullPointerExceptionForNullParam() {
    assertExceptionForParam(null, NullPointerException.class);
}

private void assertExceptionForParam(String param, Class expectedExceptionClass) {
    thrown.expect(expectedExceptionClass);
    testedObject.supposedToFail(param);
}

In case of test failure you will have clear understanding where and when it failed and also your code won't contain a lot of boilerplate.

于 2018-08-09T11:53:14.453 回答
-1

请注意,这不是 junit 的解决方案,但让我分享如何在以下位置实现相同的测试spock

def "supposedToFail(String) throws IllegalArgumentException when the given argument is null or blank"() {
    when:
    testedObject.supposedToFail(givenArgument)

    then:
    thrown(IllegalArgumentException)

    where:
    givenArgument << [null, '', '       ', '\n']
}

Spock可以与junit一起用于您的Java项目,没有任何问题。

于 2018-01-04T01:13:57.440 回答