Pewu
Pewu

Reputation: 55

Is it possible to test if exception was thrown even if it was caught?

Is it possible to @Test if an appropriate exception was thrown in the main code function eaven if it was catch in a try / catch block?

ex:

public int maxSum(int a, int b) {
    try {
        if (a + b > 100)
            throw new TooMuchException("Too much! Sum reduced to 50");
    } catch (TooMuchException e) {
        System.out.println(e);
        return 50;
    }
    return a + b;
} 

To be tested by somethink like this

@Test
void maxSum_TooMuchExceptionThrowedAndCatchedWhenSumOfNumbersIsOver100() {
    Service service = new Service();
    assertThatThrownBy(() -> {
        service.maxSum(55, 66);
    }).isInstanceOf(TooMuchException.class)
            .hasMessageContaining("Too much! Sum reduced to 50");
}

.

public class TooMuchException extends Throwable {
    public TooMuchException(String message) {
        super(message);
        }
}

Test Exception not the message.

I care about this because I want to be able to catch exceptions in function without crashing the program.

Upvotes: 0

Views: 361

Answers (1)

Nathan Hughes
Nathan Hughes

Reputation: 96385

The test's job is to confirm that the code's behavior is as expected, which means: the code does what it needs to do. Tests should not verify implementation details.

Your exception being thrown and caught is an implementation detail because the outside program doesn't know or care about it. In this case it would be very reasonable to look at this code and conclude that throwing an exception here is useless (or badly performing, because creating a stack trace has a cost) and it should be removed. Yet if you add code in the test to check for the exception somehow, say by reading the stack trace written to stdout (very do-able if you know the io classes, just fiddly and brittle), then you will have wasted your time implementing that check and you will also make extra work for the task of changing the implementation. Somebody has to look at it, understand it, and check that it's safe to remove it.

That is why we try to avoid testing implementation details, there is always the chance we will have a defect or performance issue or design change that requires modifying our implementation. We can't always avoid rewriting the test, sometimes part of the problem is that the contract was not defined right or circumstances' changing have made it irrelevant. But if we can have the test check behavior only, then we have a better chance of bring able to write a new implementation and run it against the old test, verifying that the new version does what the old one did. Updating tests is work and we want to minimize our workload when maintaining tests.

Upvotes: 2

Related Questions