Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it a good idea to catch AssertionError in JUnit tests?

Tags:

java

junit4

I have an object as the result of an API call and I want to assert the values of a member variable.

This value can be one of the two expected values depending on what the API call "sees" first and sets first. So if the assertion on one value fails, I want to assert for another value before declaring the test as a failure.

What is the best way of doing this? What I have right now is:

try {
    assertEquals("message", someObject.getValue1(), expectedValue1); 
} catch(AssertionError ae) {
    assertEquals("message", someObject.getValue1(), expectedValue2); 
}

I am just not sure if this is an acceptable practice. Please comment.

like image 632
Shine Avatar asked Aug 14 '13 01:08

Shine


People also ask

Can AssertionError be caught?

You can't. AssertionError inherits from Error which means try... catch won't be able to handle them.

How do you handle AssertionError in Junit?

In order to handle the assertion error, we need to declare the assertion statement in the try block and catch the assertion error in the catch block.

What is AssertionError in Junit?

assertTrue and assertFalse methods can throw java.lang.AssertionError in java > assertTrue(boolean) - Method tests whether a value returned is true in java. assertFalse(boolean) - Method tests whether a value returned is false in java. Read : How to enable Assertions - assert keyword in eclipse in java.

What causes java Lang AssertionError?

As with many other languages, the AssertionError in Java is thrown when an assert statement fails (i.e. the result is false). Within today's article we'll explore the detailed of the AssertionError by first looking at where it sits in the larger Java Exception Hierarchy.


3 Answers

Using exceptions as a sort of glorified goto statement is generally not a good practice. Or at least you will run into people in your career who take a dim view of using exceptions for program flow control.

How about:

Assert.assertTrue((someObject.getValue1().equals(expectedValue1) || (someObject.getValue2().equals(expectedValue2));
like image 160
Dominic Tracey Avatar answered Oct 01 '22 13:10

Dominic Tracey


Depends on the purpose, automated functional testing or unit testing. I sometimes do this for the former:

try {
    assertTrue(boolean condition from earlier in test method to check);
}
catch(AssertionError uhOh) {
     Logger.err("condition X failed: detailed info msg"); // broken item #1

}

try {
    assertTrue(another condition in same method to check);
}
catch(AssertionError yuck) {
     Logger.err("condition X failed: detailed info msg"); // another broken item
     fail(); // now blow up as we've checked everything
}

Of course that's using logback Logger and JUnit's Assert.fail() which fails the test method. This way I know of all failures for this method rather than blowing up after the first. In my case, I'm testing a rich-content web app (dialogs and pages that take a lot of user input).

Downside of "fail-fast" (using no catches) is finding one problem, fixing it, running again and finding a new one ("rinse and repeat"), but if used for unit testing this is an asset due to the modularity of the tests (ideally you are only testing one aspect of an item per test).

like image 35
DYezek Avatar answered Oct 01 '22 11:10

DYezek


I'll agree with Aquilon regarding this not being good practice.

However, can you use mocking or some other mechanism to "force" the API "see" one item before the other? That way your tests can reflect the conditions that lead to one assertion being true in one test, and the other assertion being true in another test.

like image 39
Steven M. Wurster Avatar answered Oct 01 '22 12:10

Steven M. Wurster