15

I have code where I check the exceptions in jUnit. I want to know which of the following is a good jUnit practice?

First

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

@Test
public void checkNullObject() throws CustomException {
    exception.expect(CustomException.class);
    MyClass myClass= null;
    MyCustomClass.get(null);
}

Second

@Test(expected=CustomException.class)
public void checkNullObject() throws CustomException {
    MyClass myClass= null;
    MyCustomClass.get(null);    
}

EDIT: Please note that CustomException is a unchecked custom exception. (Though it won't have any impact on this question).

4

2 回答 2

19

It depends what you want to check in the exception. If all you're doing is checking that the exception is thrown, then using @Test(expected=...) is probably the easiest way:

@Test(expected=CustomException.class)
public void checkNullObject() throws CustomException {
  MyClass myClass= null;
  MyCustomClass.get(null);
}

However, the @Rule ExpectedException has a lot more options, including checking the message, from the javadoc:

// These tests all pass.
public static class HasExpectedException {
    @Rule
    public ExpectedException thrown= ExpectedException.none();

    @Test
    public void throwsNothing() {
        // no exception expected, none thrown: passes.
    }

    @Test
    public void throwsNullPointerException() {
        thrown.expect(NullPointerException.class);
        throw new NullPointerException();
    }

    @Test
    public void throwsNullPointerExceptionWithMessage() {
        thrown.expect(NullPointerException.class);
        thrown.expectMessage("happened?");
        thrown.expectMessage(startsWith("What"));
        throw new NullPointerException("What happened?");
    }

    @Test
    public void throwsIllegalArgumentExceptionWithMessageAndCause() {
        NullPointerException expectedCause = new NullPointerException();
        thrown.expect(IllegalArgumentException.class);
        thrown.expectMessage("What");
        thrown.expectCause(is(expectedCause));
        throw new IllegalArgumentException("What happened?", cause);
    }
}

So you can check for the message, the original cause of the exception. For checking the message, you can use matchers, so you can check startsWith() and similar.

One reason to use the old style (Junit 3) throw/catch is if you have specific requirements. There aren't many of these, but it can happen:

@Test
public void testMe() {
    try {
        Integer.parseInt("foobar");
        fail("expected Exception here");
    } catch (Exception e) {
        // OK
    }
}
于 2012-07-11T09:25:27.893 回答
0

The second version is definitely the standard way to do it. The old school way to do it, before Junit 4 looked like:

try {
    codeThatShouldThrowException();
    fail("should throw exception");
} catch (ExpectedException expected) {
    //Expected
}

Sometimes you might want to revert to this way, for example if you want to assert something about the message in the exception.

于 2012-07-11T06:32:30.493 回答