I am looking to handle a multi-level error handling scenario, where I have a test looks somehwat like this:
void tester() {
String fileName = Path.of(myDir, "file_1.lo").toString();
assertThrows(
Error.class,
() -> TheCompilerClass.parent_method_called_by_testcase(fileName),
"Expected parse error to be thrown for this test"
);
assertTrue(getStdErr().contains("Failed to compile"));
}
And this invokes the code I have developed where upon exception I am trying to send back something that will result in bool: True at the assertTrue statement above.
My code structure is like this:
parent_method_called_by_testcase() {
try {
} catch (Exception e) {
System.err.println("Failed to compile ");
//how do I return the right thing?
//STDERR statements can't be returned back to test case invoking methoid?
}
}
child_method {
//this finds that exception has occurred and should pass it up the chain
//should this have a throw statement? or just a return?
if (exception) {
tell the parent so that parent can tell the testcase
}
}
Arguably, log lines like the one you mention are not part of what is generally tested in unit tests. More commonly, we test end functionality. For example, if the child method encounters a case where we throw an exception, does the parent method catch that? In other words, does the parent method throw an exception as well? This is an example of an assertion that one might write in a unit test.
Here, based on your test, your, assertThrows means that you expect the parent method to throw an exception here. So in your catch block, you would do some logging but ultimately throw e if you want the parent to throw if the child does.
parent_method_called_by_testcase() {
try {
...
} catch (Exception e) {
System.err.println("Failed to compile ");
throw e;
}
}
Related
I am trying to handle an exception 2 times
The first is in the core of a defined method :
Class Class1 {
public int method (int a, String b) {
try {
System.out.println(a+" "+b.length());
}
catch (NullPointerException e) {
// TODO: handle exception
System.out.println("catch from the method");
}
finally {
System.out.println("finally from the method");
}
return 0;
}
}
and the second
is when I call this method in main and passing a null parameter to it :
public Class Class2 {
public static void main(String[] args) {
// TODO Auto-generated method stub
Class1 c = null;
try {
c = new Class1();
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
try {
c.method(1, null);
}
catch (Exception e) {
// TODO: handle exception
System.out.println("catch from the main");
}
finally {
System.out.println("finally from the main");
}
System.out.println("\nEnd of the main");
}
}
and the result is :
catch from the method
finally from the method
finally from the main
End of the main
And now my question is, why the catch block in the main was not executed?
Once you catch an Exception, it doesn't go any further, but you can throw it again. If you want your main to also see the exception you need to throw the exception again after it is caught. Try this:
public int method (int a, String b) throws NullPointerException{
try {
System.out.println(a+" "+b.length());
}
catch (NullPointerException e) {
// TODO: handle exception
System.out.println("catch from the method");
throw e;
}
finally {
System.out.println("finally from the method");
}
return 0;
}
Notice since there is a throw in the function now, you need to include it in the function definition
Edit: As stated by a couple of people, NullPointerException does not really need to be caught because it is an unchecked exception. This is because it is a subclass of RuntimeException.
You find many texts on the mechanics of throwing and catching exceptions. What I find more important is how to make best use of the exceptions concept.
This is not exactly an answer to your question, but maybe clarifies some concepts behind the situation at hand.
Rules of Thumb
If a method fulfilled its job, it should return normally. If it failed to do so, it should throw an exception instead of the normal return. The exception coming out of your method should contain information on the problem (most of the standard exceptions already do that quite well).
In a subordinate method, you normally shouldn't use try/catch. If something goes wrong (some exception arises inside your method), then your method typically can't complete its job, it should tell its caller by means of an exception, and the easiest way is to just let the exception ripple through.
In a top-level method (e.g. main, main-menu action, button-click action), catch all exceptions, inform the user (and maybe the administrator) and continue (if possible/appropriate).
If your method gets one exception (e.g. a NullPointerException) and wants to show a different one to its caller, catch the exception, create the desired new one, using the original one as cause, and throw this new exception. Personally, I try to avoid this "exceptions translation" as much as possible.
Use finally if you have to close some resource that you obtained inside the body, that would stay blocked for extended periods of time if not closed. Think of I/O streams, database connections/transactions and similar things. Don't do it just for memory allocation, that's the garbage collector's job.
If you follow these rules, you'll find that your code can concentrate on its main job, isn't cluttered with lots of error handling, and still is robust in case of exceptions.
Your Example
It all depends on the question "What's the job of Class1.method()?".
That might be "Print these two numbers". Then, when it gets the NullPointerException, it won't fulfill its job, so it shouldn't return normally, and instead exit with an exception, most easily by doing nothing (no try/catch at all) and just letting the exceptions framework do its automatic job. That will mean that its caller gets the original NullPointerException:
public int method (int a, String b) {
System.out.println(a+" "+b.length());
}
If the job of Class1.method() were "Print these two numbers, but only if there is a string", then you should catch the NullPointerException inside (or better, check with an if) and return normally ("I've done my job!"). Then Class2.main() should be satisfied with the non-printing in case of null, and have no reason to do any error handling after calling Class1.method(). If Class2.main() doesn't want that behaviour, it shouldn't call Class1.method() in that case.
#Test
public void test() throws Exception
{
try
{
//some code over here
}
catch(Exception e)
{
if(e.toString() == null)
{
System.out.print("Test Case: Successful");
}
else
{
System.out.println("Test Case: Failed");
System.out.println("Failing Reason: "+ e.toString());
}
}
}
Currently I have the above code.
However, when executing the JUnit.
Nothing was printed into the console.
Did I do anything wrong? Or is it that i cannot use System.out.println in JUnit.
So I have a second question:
Is it possible to print out the total amount of time taken to complete the JUnit test?
This code doesn't make sense.
If no exception is thrown, no exception is thrown, so you won't end up in the catch block; so there isn't a way you'd end up there in the "successful" case (unless you're testing explicitly for throwing an exception whose getMessage() returns null, which is... hmm; and in that case you should have a fail() as the last line of the try)
JUnit already handles failures for you. If your approach were the "right" way to do it, you'd have to put this code in every test case. What a lot of repeated code.
If the code in the try block fails by throwing an Exception, you catch and swallow the problem. Sure, it gets printed to the console, but JUnit has no means of capturing that, so it looks like the test passes. (It will still fail properly if an Error or other Throwable is thrown).
In short: just get rid of your try/catch block, leaving the code in the try, and let the testing framework do exactly what it is designed for.
Code in the catch block will only run if the code in the try block throws an exception. As you have it coded, it is not going to print anything out unless an exception is throw. This is likely what you meant:
#Test
public void test() throws Exception
{
try
{
//some code over here
// last line of try block
System.out.print("Test Case: Successful");
}
catch(Exception e)
{
System.out.println("Test Case: Failed");
System.out.println("Failing Reason: "+ e.toString());
}
}
In try block, I want to execute two functions. If the first one failed then don't execute the second. I also want to print out which function failed.
See following code.
try {
a = func1();
b = func2(); //won't execute if a failed
}
catch (Exception e) {
//TODO: print a or b failed?
}
Does the language support this scenario naturally?
If not, is the following a good practice? (I cannot think of anything wrong about it. But it concerns me as I don't remember seeing any one using return in catch.)
try {
a = func1();
}
catch {
//print: a failed
return; //if a failed then skip the execution of b
}
try {
b = func2();
}
catch {
//print: b failed
}
EDIT:
Summary of comments:
throw different exception from two methods.
In this case the methods are written by others and I have no control.
e.printStackTrace() will print line number and function
I want to do more than just printing. More like, if a failed, execute the following code.
What you want is String methodName = e.getStackTrace()[0].getMethodName());
But this is hardly a good practice. The standard way is to log the exception using appropriate method in your logging framework or (if writing a console app, which is rarely the case with Java) to print it to the error or standard output or optionally to other PrintStream, for example using printStackTrace(printStream).
But in most cases you want to propagate exception to the upper layers and handle (or decide to not handle it) by the appropriate high level code. Catching exceptions like this leads to nasty bugs. Returning from catch black is also a very bad idea in 99% of cases because exception signalizes abnormal termination of the method while returning a value does not.
As dev-null wrote e.getStackTrace() can help. But note that the exception may not be thrown by func1 or func2 themselves but by some other method they call. So you need to go through all elements of the array until you hit func1 or func2.
Calling them in separate try blocks is definitely practiced but it can get cumbersome.
Logging the stack trace if an exception is thrown will inform you which line threw the exception. If the first line in the try/catch throws the exception, the next line will not be executed.
This will work:
String failedFunc = "func1";
try {
a = func1();
failedFunc = "func2";
b = func2(); //won't execute if func1() failed
} catch (Exception e) {
System.out.println("Func '" + failedFunc + "' failed: " + e);
}
Or course, if all you're doing is printing the error, then printing the stack trace will show you exactly where it failed. The above code is however useful if you need the value of failedFunc without a full stack trace.
As I said in the comments, you can use e.printStackTrace() to determine the cause of the Exception. Since you expressed a desire for different behaviors then you have a few options. You could write two local functions to decorate your func1 and func2 calls with custom Exceptions. Something like,
class Func1Exception extends Exception {
public Func1Exception(Exception e) {
super(e);
}
}
class Func2Exception extends Exception {
public Func2Exception(Exception e) {
super(e);
}
}
Then you can write the local functions like
private static Object func1Decorator() throws Func1Exception {
try {
return func1();
} catch (Exception e) {
throw new Func1Exception(e);
}
}
private static Object func2Decorator() throws Func2Exception {
try {
return func2();
} catch (Exception e) {
throw new Func2Exception(e);
}
}
Then you can handle them however you wish,
try {
a = func1Decorator();
b = func2Decorator(); // this still won't execute if a failed
} catch (Func1Exception e) {
// a failed.
} catch (Func2Exception e) {
// b failed.
}
If you want func2 to run even when a fails you could use a finally block,
try {
a = func1Decorator();
} catch (Func1Exception e) {
// a failed.
} finally {
try {
b = func2Decorator(); // this will execute if a fails
} catch (Func2Exception e) {
// b failed.
}
}
Code:-
try {
Assert.assertEquals("1", "2");
} catch (Exception e) {
System.out.println("I am in error block");
}
If the assert statements fails, I would like to capture the error in the catch block. I am trying with the above code and its not happening.
Will the assertion error be caught by in a catch block for java exception?
You have almost answered your own question. Your catch block will not catch the AssertionError that the Assert throws if it fails, because it is an Error (or, more specifically, it extends java.lang.Error). See the docs for more information on this. Your catch block only catches Throwable objects that extend java.lang.Exception
If you really want to catch it - you need to use
catch (AssertionError e) {
...
However, as others have mentioned, this is a very unusual way to use assertions - they should usually pass and if they fail it is very unusual for you to want to carry on the program execution. That's why the failure throws an Error rather than an Exception. You can read more about (not) catching Error in this question.
If you just want a test the variable value, it is preferred to use if ( variableName == "1")
NB if you are testing unit-test helper code, like a matcher, it might make sense to catch the AssertionError.
If you want to catch both Exception and Error instances use:
...
catch (Throwable t)
{
...
}
Since both Exception and Error extend Throwable.
Well, I believe you are using JUnit for writing your tests. In that case, you should not catch your Assert.assertEquals() because they should pass for normal test execution. If it throws any exception, it means that your code is not performing as it should.
If you want to catch the errors in that way you need something like the following:
if (num == 1 || num == 2) {
throw new Exception();
}
You could create your own exception class and pass in the message you want.
Basically iterating through a list and,
- Invoke method on first object
- Catch the first exception (if any); if there are no more exceptions to catch, return normally. Otherwise, keep on invoking method until all exceptions are caught.
- Move on to next object.
I can iterate through each object, invoke the method, and catch one exception but I do not know how to continuously invoke the method on it and keep on catching exceptions.
This is similar to the other answers, but without the flag, which seems like clutter to me. I don't really understand the question though, so I'm just throwing it out there in case it is useful.
for (Item item : items) {
while (true) {
try {
item.doSomething();
break;
} catch (MyException ex) {
log.warn("Something failed.", ex);
}
}
}
This approach hinges on the operation of the unlabeled break statement, which completes abruptly and then exits the enclosing while statement normally.
Based on subsequent comments, I think there is some confusion about what it means when there are multiple exceptions declared to be thrown by a method.
Each invocation of a method can be terminated by just one exception being thrown. You can't somehow resume invocation where it left off, and handle subsequent exceptions.
So, if a method throws multiple exceptions, catch a common ancestor, and move on. For example, if a method throws java.io.EOFException or java.nio.channels.ClosedChannelException, you could simply catch java.io.IOException since it is a common ancestor. (You could also catch java.lang.Exception or java.lang.Throwable for the same reason.) Invoking the method again under the same conditions won't get you any further.
If you want to attempt to invoke the method on each object, even if some fail, use this:
for (Item item : items) {
try {
item.doSomething();
} catch (Exception ex) { /* This could be any common ancestor. */
log.warn("Something failed.", ex);
}
}
If you're talking about dealing with a single method call that will throw more than one exception, it can't be done -- no matter how many times you call the method, it will keep on throwing the first exception. You can't go back into the method and keep running from there; after throwing one exception, it's all over.
But if you're talking about a method that sometimes throws exceptions and sometimes doesn't, try something like this:
boolean thrown = false;
do {
try {
thrown = false;
method();
}
catch (Exception e) {
thrown = true;
// Handle as you like
}
} (while thrown);
This is what I understand.
You have an object's method which may throw a number of exceptions.
What you want to do is to catch them all and continue with the next object in the list.
Is that correct?
So, that would be:
for( YourObject o : yourList ) {
try {
o.thatMethod();//invoke that risky method
} catch( SomeExceptionClass sec ) {
// Do something with that exception
} catch( SomeOtherExceptionClass soec ) {
// Do something with that exception
} catch( YetAnotherxceptionClass yaec ) {
// Do something with that exception
} catch( OtherUnRelatedException oue ) {
// Do something with that exception
}
}
When you do this, if the invocation of thatMethod() throws an exception and that exception is listed in the catch section, the execution flow will jump to that exception and after it will continue to the normal flow ( which is the for loop and will continue with the next object )
I hope this is what to need. For more information read: The catch block in the Java Tutorial section Essential classes
I'm assuming that you are trying to performs some kind of validation to the items in a list, where the validation errors are reported by throwing exceptions. I'm also assuming that you are trying to collect all of the validation errors.
The simple answer is that this problem cannot be solved using this approach. To understand why, take a look at this:
boolean exceptionCaught = false;
do {
try {
item.doSomething();
} catch (MyException e) {
exceptionCaught = true;
}
} while (exceptionCaught);
This fails because each time you call item.doSomething() it is going to throw an exception at exactly the same place. The net result is an infinite loop.
The best you can do with this approach is to capture the first exception for each item in the list.
So how can you achieve what you are trying to achieve? The answer is that you have to change the validation code to use some other way to report errors than throwing exceptions. For example, you could change:
class Item {
...
void validate() {
if (noHat) {
throw new MyException("bad hat");
}
if (noPants) {
throw new MyException("world-wide pants");
}
}
}
to something like this:
class Item {
...
void isValid(List<MyException> errors) {
boolean ok = true;
if (noHat) {
errors.add(new MyException("bad hat"));
ok = false;
}
if (noPants) {
errors.add(new MyException("world-wide pants"));
ok = false;
}
return ok;
}
}
Messy huh! You could sugar this in various ways, but this style of error reporting is always going to be more complicated. But I don't think there is a practical way to avoid the messiness AND capture ALL of the validation errors.