JUnit handling of RuntimeException (specifically)

10.2k views Asked by At

I tend to throw as many checked Exceptions up as possible: it declutters the code (and I regard checked Exceptions as a dubious aspect of Java). I tend to use them when "refining" code.. i.e. when it makes sense for the particular context.

This approach gets slightly complicated when overriding superclass/interface methods which don't throw the requisite Exception, and therefore I tend to do this:

@Override
public void close() {
    try {
        _close();
    } catch (Exception e) {
        throw new RuntimeException(e);
    }
}

where _close is a private method which does all the business.

The problem when it comes to JUnit, if you actually want to test something where an exception is thrown by _close() is that the resulting RuntimeException seems to be handled by JUnit in an "unconditional" way: it seems always to stop the test with a failure message... even if you actually catch and deal with it in a try .. catch!

There is a sort of "workaround" for this which I've found (the CUT class closes all its closeableComponents when it is closed):

@Test (expected = RuntimeException.class)
public void errorFlagShouldBeSetIfAnyCloseablesThrowExceptionWhenCUTCloses() throws Exception {
    Closeable spyCloseable = spy( new Closeable(){
        @Override
        public void close() throws IOException {
            throw new IOException( "dummy" );
        }});
    spyCUT.addCloseableComponent( spyCloseable );
    Exception blob = null;
    try{
        spyCUT.close();
    }catch( Exception e ){
        blob = e;
    }
    assertThat( spyCUT.getErrorFlag() ).isTrue();
    if( blob != null ){
        throw blob;
    }

I.e. if you don't have this expected setting you always get a test failure (because of the RuntimeException "ignoring" the try .. catch). But in order to satisfy the expected you then have to rethrow the RuntimeException at the end of the test...

... is there any way of varying JUnit's handling of RuntimeExceptions?

1

There are 1 answers

4
GhostCat On BEST ANSWER

Something must be wrong in your setup. JUnit does not have any such special handling for runtime exceptions.

I put together this MCVE; and it passes.

static class CUT {
    void close(Closeable _close) {
        try {
            _close.close();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
}

@Test
public void test() throws Exception {
    Closeable spyCloseable = Mockito.spy(new Closeable() {
        @Override
        public void close() throws IOException {
            throw new IOException("dummy");
        }
    });
    Exception blob = null;
    try {
        new CUT().close(spyCloseable);
        fail("should have thrown");
    } catch (Exception e) {
        blob = e;
    }
    assertThat(blob.getMessage(), is("java.io.IOException: dummy"));
}

It is not exactly what you have up there; but "close enough" in my mind.

Long story short: your answer is coming from some other place. I suggest: do the same as I did: create a true mcve; and work your way from there!