Reputation: 3161
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.
Upvotes: 4
Views: 7808
Reputation: 34301
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.
Upvotes: 1
Reputation: 7212
someExternalMethod(value)
to force throw Exception
Test method myMethod
, checking that is not throwing Exception:
@Test
public void testMyMethod() {
try {
myMethod("value");
} catch (Exception ex) {
Assert.fail();
}
}
Upvotes: 0
Reputation: 726469
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
.
Upvotes: 2
Reputation:
catch
blocks are evaluated in the order they are.
Your code works fine: in case of IllegalArgumentException
, Exception
block will be ignored.
Upvotes: 0