1

I am new to java, Junit and jacoco. I am doing exception handling as below. I am catching Exception class as well in case the method throws any other exception that were missed to catch earlier.

private void myMethod1() throws MyCustomException {
    ....
    try {
        ..... straight JDBC calls for select, insert, update operations ....
    } catch (SQLException sqEx) {
        logger.error(....);
        new MyCustomException(.....);
    } catch (RuntimeException rEx) {
        logger.error(....);
        new MyCustomException(.....);
    } catch (Exception ex) {
        logger.error(....);
        new MyCustomException(.....);
    }
}

in Junit test, tried below. When I have runtime any exception I throw is always going to RuntimeException catch block itself unless I throw Exception. which other checked exception can I try so it goes into Exception catch block. Due to this I am unable to get the code coverage needed.

private void testMyMethod1() {
    ....
    try {
        .....
        when(...).thenThrow(new SocketException());

        spy.myMethod1();
    } catch (SQLException sqEx) {
        assertTrue(false);
    } catch (RuntimeException rEx) {
        assertTrue(false)
    } catch (Exception ex) {
        assertTrue(true);
    }
}

your help is appreciated.

3 Answers 3

1

In thenThrow you have throwed socket exception,but you are trying to catch some other exception like SQLException. If the exception thrown is not a child of SQLException then it won't come into that block.

Also please make sure you are creating proper exception inside when()..thenThrow() statement by debugging.Sometimes creating inappropriate exception will cause problems.

Sign up to request clarification or add additional context in comments.

Comments

1

A few things... if your myMethod1() is not in the same java class, you can't test a private method in a separate unit test class. Its best to make your myMethod1() package protected. In your test class, its also best not to have any try catch or if statements inside it. You must make separate test methods per test case, not all in one. You can take advantage of @Rule or @expected annotations. I recommend doing something like this...

@Test(expected = MyCustomException.class)
public void testMyMethod1_handlesSQLException(){

     doThrow(SQLException.class).when(...);

     Foo foo = new Foo();
     foo.myMethod1();
}

@Test(expected = MyCustomException.class)
public void testMyMethod1_handlesRuntimeException(){

     doThrow(RuntimeException.class).when(...);

     Foo foo = new Foo();
     foo.myMethod1();
}

@Test(expected = MyCustomException.class)
public void testMyMethod1_handlesException(){

     doThrow(Exception.class).when(...);

     Foo foo = new Foo();
     foo.myMethod1();
}

Comments

1

In JUnit 5, a possible way would be:

@ParameterizedTest
@ValueSource(classes = { 
  SQLException.class, 
  RunTimeException.class, 
  Exception.class
})
void methodWrapsException(Exception toBeWrapped) {
  Foo foo = new Foo(...);
  doThrow(toBeWrapped).when(...);
  assertThrows(MyCustomException.class, () -> foo.myMethod1());
}

This makes use of JUnit 5 support for parameterized classes and its lambda-based assertions for exceptions.

3 Comments

unfortunately, the code I cover using assertThrows is not shown as covered, even though the test passes.
This may be due to the limitations of the coverage tool used. See for example the FAQ for JaCoCo.
Hi, @EmeraldTablet did you find any way to bring the code under coverage when assertThrows are used?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.