Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to assert that an exception is caught?

I know how to assert that an Exception is thrown. But, how can I assert that an Exception was thrown and it was successfully caught? For example, say I have a method which should throw a particular type of exception for invalid inputs

public static void myMethod(String value) {
    try {
        someExternalMethod(value);// can throw IllegalArgumentException
    } catch (IllegalArgumentException e) {
        System.out.println("Let me handle it differently");
    } catch (Exception e) {
        System.out.println("Not IllegalArgumentException");
    }
}

Now I want to assert that for some values the method indeed has thrown 'IllegalArgumentException' and not some other Exception.

like image 775
Shiva Kumar Avatar asked Sep 05 '25 16:09

Shiva Kumar


2 Answers

In the context of testing myMethod you cannot (and more importantly, you should not want to) check that someExternalMethod has thrown IllegalArgumentException. In fact, your tests of myMethod should not assume that a call of someExternalMethod has been made: it is an implementation detail of myMethod.

The very reason myMethod catches these exceptions is to hide them from its callers. You should check that these exceptions are hidden from you by passing values that cause them, and verifying that nothing is thrown in both cases.

Testing someExternalMethod, along with the exceptions that it throws, is the task accomplished by testing someExternalMethod, not myMethod.

like image 200
Sergey Kalinichenko Avatar answered Sep 07 '25 07:09

Sergey Kalinichenko


You're missing the important point of unit testing - tests should test behaviour, not implementation.

Given this assumption you should be testing the behaviour of myMethod is as expected when an IllegalArgumentException occurs. It's hard to say any more than that with the method you've shown given the parameter, a single String is immutable, there is no return value and no exceptions are thrown.

A better example might be this method (which is a little contrived to demonstrate the point):

public double divide(int numerator, int denominator)
{
  try
  {
    return numerator / denominator;
  }
  catch (ArithmeticException e)
  {
    return Double.NaN;
  }
}

Where your tests would assert that the division is correct and that when an error occurs NaN is returned, like this:

@Test
public void testDivide()
{
  assertEquals(2.0, divide(4, 2), 0);
}

@Test
public void testDivideByZero()
{
  assertTrue(Double.isNaN(divide(1, 0));
}

You could then re-write the divide method like this:

public double divide(int numerator, int denominator)
{
  if (denominator == 0)
  {
    return Double.NaN;
  }
  else
  {
    return numerator / denominator;
  }
}

And the tests would confirm the operation of my system because the behaviour of the divide method remains unchanged.

like image 28
Nick Holt Avatar answered Sep 07 '25 07:09

Nick Holt