Search code examples
javajunitexpected-exception

How can I use JUnit's ExpectedException to check the state that's only on a child Exception?


I'm trying to refactor this old code that does not use ExpectedException so that it does use it:

    try {
        //...
        fail();
    } catch (UniformInterfaceException e) {
        assertEquals(404, e.getResponse().getStatus());
        assertEquals("Could not find facility for aliasScope = DOESNTEXIST", e.getResponse().getEntity(String.class));
    }

And I can't figure out how to do this because I don't know how to check the value of e.getResponse().getStatus() or e.getResponse().getEntity(String.class) in an ExpectedException. I do see that ExpectedException has an expect method that takes a hamcrest Matcher. Maybe that's the key, but I'm not exactly sure how to use it.

How do I assert that the exception is in the state I want if that state only exists on the concrete exception?


Solution

  • The "best" way is a custom matcher like the ones described here: http://java.dzone.com/articles/testing-custom-exceptions

    So you would want something like this:

    import org.hamcrest.Description;
    import org.junit.internal.matchers.TypeSafeMatcher;
    
    public class UniformInterfaceExceptionMatcher extends TypeSafeMatcher<UniformInterfaceException> {
    
    public static UniformInterfaceExceptionMatcher hasStatus(int status) {
        return new UniformInterfaceExceptionMatcher(status);
    }
    
    private int actualStatus, expectedStatus;
    
    private UniformInterfaceExceptionMatcher(int expectedStatus) {
        this.expectedStatus = expectedStatus;
    }
    
    @Override
    public boolean matchesSafely(final UniformInterfaceException exception) {
        actualStatus = exception.getResponse().getStatus();
        return expectedStatus == actualStatus;
    }
    
    @Override
    public void describeTo(Description description) {
        description.appendValue(actualStatus)
                .appendText(" was found instead of ")
                .appendValue(expectedStatus);
    }
    

    }

    then in your Test code:

    @Test
    public void someMethodThatThrowsCustomException() {
        expectedException.expect(UniformInterfaceException.class);
        expectedException.expect(UniformInterfaceExceptionMatcher.hasStatus(404));
    
        ....
    }