I am trying to follow this tutorial JUnit 5: How to assert an exception is thrown?
I use Java 10, IntelliJ 2018 and Junit 5.
I make a calculator app that adds 2 fractions. It checks whether the input has 0 in the denominator.
When I run the test The exception Message get printed out "Undefined Math Expression" but my IDE says "Expected java.lang.Throwable to be thrown, but nothing was thrown." I think there is some problem with the scope of my code? I'm a newbie, please be kind. I provided the code and the test below:
public class Calculator {
public static int[] calculate (int firstNumerator, int firstDenominator, int secondNumerator, int secondDenominator) {
String exceptionMessage = "Undefined Math Expression";
int resultNumerator;
int resultDenominator;
int[] result = new int[2];
resultNumerator = (firstNumerator * secondDenominator) +
(secondNumerator * firstDenominator);
resultDenominator = firstDenominator * secondDenominator;
try {
if (resultDenominator == 0) {
throw (new Throwable(exceptionMessage));
} else {
result[0] = resultNumerator;
result[1] = resultDenominator;
}
} catch (Throwable e) {
System.out.println(e.getMessage());
}
return result;
}
}
The test:
class CalculatorTest {
#Test
void denominatorContainsZero() {
assertThrows(Throwable.class, () -> {
Calculator.calculate(0,0,0,0);
});
}
}
The misunderstanding here appears to be in what JUnit can actually see.
JUnit isn't magical: it's just plain old Java. It can't see inside your methods to see what they are doing. All it can see is what any other code can see when it executes a method: the return value and uncaught exceptions (as well as any side effects of the method, if they are visible to the calling code).
Your method here doesn't throw an exception from the perspective of a caller: internally, it throws the exception, but it catches and handles it.
If you want JUnit to test that an exception is thrown, you need to not catch that exception.
It is never (*) the right thing to do to throw an exception and then catch and handle it yourself. What's the point? You can simply do the thing you do to handle it, without throwing the exception. Exceptions are expensive to throw, because of the need to capture the entire stack trace.
Throwable is never (*) the right exception to throw. It's the exception "equivalent" of returning Object: it conveys no type information about the exception to the caller, who then either has to do a lot of work to try to handle it; or, more realistically, should just propagate it themselves. IllegalArgumentException is the right exception to throw here, if you actually needed to throw (and not catch) an exception.
Throwable is rarely the right thing to catch. Throwable is a supertype of both Exception and Error, so you might unintentionally catch an Error, like OutOfMemoryError, which shouldn't be caught because there is nothing reasonable to do except crash your program. Catch the most specific type you can; which also means that you should throw the most specific type you can (or, at least, a type appropriate to the abstraction).
(*) This is "never" as in "ok, there are a limited number of circumstances where it may be appropriate". But unless you understand what these are, don't.
The Throwable is catched by try catch block, so Junit can not access it. Try remove the try catch block.
You are not actually throwing exception, you are catching it. For this to work, you should remove try catch block.
Related
I am confused why it is going to catch and print the error occurred message when I run my code since it runs and just prints the message I can't tell what the error could be
Note: this is my very first time using try and catch my professor told us to use it but haven't really learned how it works fully yet so I'm not sure if the problem is with that or if it's just with my code
public static void main (String [] args) {
try {
File file = new File("in.txt");
Scanner scanFile = new Scanner(file);
...
} catch(Exception e) {
System.out.println("Error");
}
}
Do not catch an exception unless you know what to do. It is common that you don't - most exceptions aren't 'recoverable'.
So, what do you do instead?
Simplest plan: Just tack throws Exception on your main method. public static void main(String[] args) methods should by default be declared to throws Exception, you need a pretty good reason if you want to deviate from this.
Outside of the main method, think about your method. Is the fact that it throws an exception an implementation detail (a detail that someone just reading about what the method is for would be a bit surprised by, or which could change tomorrow if you decide to rewrite the code to do the same thing but in a different way)? In that case, do not add that exception to the throws clause of your method. But if it is, just add it. Example: Any method whose very name suggests that file I/O is involved (e.g. a method called readFile), should definitely be declared to throws IOException. It'd be weird for that method not to throws that.
Occasionally you can't do that, for example because you're overriding or implementing a method from an interface or superclass that doesn't let you do this. Or, it's an implementation detail (as per 2). The usual solution then is to just catch it and rethrow it, wrapped into something else. Simplest:
} catch (IOException e) {
throw new RuntimeException("uncaught", e);
}
Note that the above is just the best default, but it's still pretty ugly. RuntimeException says very little and is not really catchable (it's too broad), but if you don't really understand what the exception means and don't want to worry about it, the above is the correct fire-and-forget. If you're using an IDE, it probably defaults to e.printStackTrace() which is really bad, fix that template immediately (print half the details, toss the rest in the garbage, then just keep on going? That's.. nuts).
Of course, if you know exactly why that exception is thrown and you know what to do about it, then.. just do that. Example of this last thing:
public int askForInt(String prompt) {
while (true) {
System.out.println(prompt + ": ");
try {
return scanner.nextInt();
} catch (InputMismatchException e) {
System.out.println("-- Please enter an integral number");
}
}
}
The above code will catch the problem of the user not entering an integer and knows what to do: Re-start the loop and ask them again, until they do it right.
Just add throws Exception to your main method declaration, and toss the try/catch stuff out.
There are a couple of problems with your current code:
catch (Exception e) {
System.out.println("Error occured...");
}
Firstly, you are not printing any information about the exception that you caught. The following would be better:
catch (Exception e) {
System.out.println(e.getMessage()); // prints just the message
}
catch (Exception e) {
System.out.println(e); // prints the exception class and message
}
catch (Exception e) {
e.getStackTrace(System.out); // prints the exception stacktrace
}
Secondly, for a production quality you probably should be logging the exceptions rather than just writing diagnostics to standard output.
Finally, it is usually a bad idea to catch Exception. It is usually better to catch the exceptions that you are expecting, and allow all others to propagate.
You could also declare the main method as throws Exception and don't bother to catch it. By default, JVM will automatically produce a stacktrace for any uncaught exceptions in main. However, that is a lazy solution. And it has the disadvantage that the compiler won't tell you about checked exceptions that you haven't handled. (That is a bad thing, depending on your POV.)
now null printed out.
This is why the 2nd and 3rd alternatives are better. There are some exceptions that are created with null messages. (My guess is that it is a NullPointerException. You will need a stacktrace to work out what caused that.)
Catching Exception e is often overly broad. Java has many built-in exceptions, and a generic Exception will catch all of them. Alternatively, consider using multiple catch blocks to dictate how your program should handle the individual exceptions you expect to encounter.
catch (ArithmeticException e) {
// How your program should handle an ArithmeticException
} catch (NullPointerException e) {
// How your program should handle a NullPointerException
}
I am going through a socket program. In it, printStackTrace is called on the IOException object in the catch block.
What does printStackTrace() actually do?
catch(IOException ioe)
{
ioe.printStackTrace();
}
I am unaware of its purpose. What is it used for?
It's a method on Exception instances that prints the stack trace of the instance to System.err.
It's a very simple, but very useful tool for diagnosing an exceptions. It tells you what happened and where in the code this happened.
Here's an example of how it might be used in practice:
try {
// ...
} catch (SomeException e) {
e.printStackTrace();
}
Note that in "serious production code" you usually don't want to do this, for various reasons (such as System.out being less useful and not thread safe). In those cases you usually use some log framework that provides the same (or very similar) output using a command like log.error("Error during frobnication", e);.
I was kind of curious about this too, so I just put together a little sample code where you can see what it is doing:
try {
throw new NullPointerException();
}
catch (NullPointerException e) {
System.out.println(e);
}
try {
throw new IOException();
}
catch (IOException e) {
e.printStackTrace();
}
System.exit(0);
Calling println(e):
java.lang.NullPointerException
Calling e.printStackTrace():
java.io.IOException
at package.Test.main(Test.java:74)
It helps to trace the exception. For example you are writing some methods in your program and one of your methods causes bug. Then printstack will help you to identify which method causes the bug. Stack will help like this:
First your main method will be called and inserted to stack, then the second method will be called and inserted to the stack in LIFO order and if any error occurs somewhere inside any method then this stack will help to identify that method.
printStackTrace() helps the programmer to understand where the actual problem occurred. printStacktrace() is a method of the class Throwable of java.lang package. It prints several lines in the output console.
The first line consists of several strings. It contains the name of the Throwable sub-class & the package information.
From second line onwards, it describes the error position/line number beginning with at.
The last line always describes the destination affected by the error/exception. The second last line informs us about the next line in the stack where the control goes after getting transfer from the line number described in the last line. The errors/exceptions represents the output in the form a stack, which were fed into the stack by fillInStackTrace() method of Throwable class, which itself fills in the program control transfer details into the execution stack. The lines starting with at, are nothing but the values of the execution stack.
In this way the programmer can understand where in code the actual problem is.
Along with the printStackTrace() method, it's a good idea to use e.getmessage().
printStackTrace() prints the locations where the exception occurred in the source code, thus allowing the author who wrote the program to see what went wrong. But since it shows problems in the source code, the user(s) who may or may not have any coding experience may not be able to understand what went wrong, so if the program allows the user to send error messages to the authors, the users may not be able to give good data on what went wrong.
You should consider the Logger.getLogger() method, it offers a better exception handling (logging) facility, and besides printStackTrace() without arguments is considered to be obsolete and should ONLY be used for debugging purposes, not for user display.
The printStackTrace() helps the programmer understand where the actual problem occurred. The printStackTrace() method is a member of the class Throwable in the java.lang package.
printStackTrace is a method of the Throwable class. This method displays error message in the console; where we are getting the exception in the source code. These methods can be used with catch block and they describe:
Name of the exception.
Description of the exception.
Location of the exception in the source code.
The three methods which describe the exception on the console (in which printStackTrace is one of them) are:
printStackTrace()
toString()
getMessage()
Example:
public class BabluGope {
public static void main(String[] args) {
try {
System.out.println(10/0);
} catch (ArithmeticException e) {
e.printStackTrace();
// System.err.println(e.toString());
//System.err.println(e.getMessage());
}
}
}
printStackTrace() helps the programmer to understand where the actual problem occurred. It helps to trace the exception.
it is printStackTrace() method of Throwable class inherited by every exception class. This method prints the same message of e object and also the line number where the exception occurred.
The following is an another example of print stack of the Exception in Java.
public class Demo {
public static void main(String[] args) {
try {
ExceptionFunc();
} catch(Throwable e) {
e.printStackTrace();
}
}
public static void ExceptionFunc() throws Throwable {
Throwable t = new Throwable("This is new Exception in Java...");
StackTraceElement[] trace = new StackTraceElement[] {
new StackTraceElement("ClassName","methodName","fileName",5)
};
t.setStackTrace(trace);
throw t;
}
}
java.lang.Throwable: This is new Exception in Java...
at ClassName.methodName(fileName:5)
What is the use of e.printStackTrace() method in Java?
Well, the purpose of using this method e.printStackTrace(); is to see what exactly wrong is.
For example, we want to handle an exception. Let's have a look at the following Example.
public class Main{
public static void main(String[] args) {
int a = 12;
int b = 2;
try {
int result = a / (b - 2);
System.out.println(result);
}
catch (Exception e)
{
System.out.println("Error: " + e.getMessage());
e.printStackTrace();
}
}
}
I've used method e.printStackTrace(); in order to show exactly what is wrong.
In the output, we can see the following result.
Error: / by zero
java.lang.ArithmeticException: / by zero
at Main.main(Main.java:10)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:147)
When there are methods that throw exceptions and you know these exceptions will not be thrown, what should you do?
Many times I see people just logging the exception, but I wonder if there is a build in exception in java that means something like: "This exception should not have been thrown".
For example, imagine I have a code that calls StaticClass.method(someObject) and this method throws a SpecificException when someObject is not valid. What should you do in the catch block?
try {
StaticClass.method(someobject);
} catch (SpecificException e) {
// what should I do here?
}
If when calling the method you know for sure that it will not throw an exception because of previous checks you should throw a RuntimeException wrapping the SpecificException.
try {
StaticClass.method(someobject);
} catch (SpecificException e) {
//This is unexpected and should never happen.
throw new RuntimeException("Error occured", e);
}
Some methods already throw a RuntimeException when they fail to perform their purpose.
//Here we know for sure that parseInt(..) will not throw an exception so it
//is safe to not catch the RuntimeException.
String s = "1";
int i = Integer.parseInt(s);
//Here instead parseInt(..) will throw a IllegalArgumentException which is a
//RuntimeException because h is not a number. This is something that should
//be fixed in code.
s = "h";
i = Integer.parseInt(s);
RuntimeExceptions don't require a try/catch block and the compiler will not be mad at you for not catch them. Usually they are thrown where something in your app code is wrong and should be fixed. Anyway there are cases where catching a RuntimeException is useful.
I am running the following code:
import java.io.FileNotFoundException;
import java.io.IOException;
class Basic1 {
int c;
void calculation(int a, int b) throws Exception {
c = a / b;
}
}
class Basic extends Basic1 {
void calculation(int a, int b) throws IOException {
c = a / b;
RuntimeException ae = new ArithmeticException();
throw ae;
}
public static void main(String[] args) {
int a = 10;
int b = 0;
int c;
Basic ba = new Basic();
try {
ba.calculation(a, b);
} catch (IOException e) {
System.out.println("Zero can't be there in the denominator. : IoException");
} catch (ArithmeticException e) {
System.out.println("Zero can't be there in the denominator. : Arthimetic Exception");
} catch (Exception e) {
System.out.println("Zero can't be there in the denominator. : Exception");
}
}
}
The program is compiling successfully and outputting "Zero can't be there in the denominator. : Arthimetic Exception" (output is as expected).
My question is how is the program able to compile successfully? Why am I not getting an error when I throw an IOException while inside calculation() I am creating a RuntimeException object?
My second question is given that the program enters the catch (ArithmeticException e) clause, is the compiler deciding at run time which catch will execute? Do I understand correctly?
For your first question, methods using the throws E (where E is some arbitrary checked exception) construct don't have to throw anything. All it means is that anyone calling your method has to be able to handle E, which allows your method to throw E without handling it. This would otherwise be a compilation error. Usually, the documentation of your method specifies when E is thrown. In the words of the JLS:
Essentially, for each checked exception that can result from execution of the body of a method or constructor, a compile-time error occurs unless its exception type or a supertype of its exception type is mentioned in a throws clause in the declaration of the method or constructor.
This doesn't say you must throw the given checked exception within the method body. Note that you can use throws with unchecked exceptions, but this has no effect on the program, as unchecked exceptions may be thrown anywhere without being handled. That's the point of them.
In your code, you throw a RuntimeException. Any class extending RuntimeException (including itself) is unchecked by definition. ArithmeticException is one of these, so you may assign it to a variable of type RuntimeException and then throw it without specifying it in the throws clause.
For your second question, I'll assume that the compiler doesn't optimise away the various catch clauses. In that case, no, the catch which is executed is not determined at compile time. When any exception is thrown in your program, it propagates up the stack until it is caught. If it isn't, it halts execution and the stack trace is printed to System.err. Since an ArithmeticException is thrown, the first catch clause does not match but the second one does, so is executed. The third one (catch (Exception e)) would match, but order matters with catch clauses and only one is executed, so that clause is not executed here.
However, in this case, it is not inconceivable that the compiler optimises away your catch clauses and directs the program straight to the code in the catch (ArithmeticException e) clause, as your method will always throw ArithmeticException. It must be considered, however, that any line of code may throw some obscure error like OutOfMemoryError; the compiler must allow for such edge cases when optimising.
As mentionend in the Subject: Java forces me to return something, because the handling of the Exception is in an own function.
public String returnLel(String mattDamon) {
try {
trick(mattDamon); // The LelException could be thrown
return "lel";
} catch (LelException e) {
handleException();
}
}
public void handleException() {
throw new RuntimeException();
}
`
Your code will not compile because the compiler is not "clever" enough to know you are throwing a RuntimeException in handleException.
In order for your code to compile you can either:
directly throw new RuntimeException(); in your catch statement (ugly)
return null after invoking handleException(); (acceptable, but still kind of ugly)
add a finally statement to finalize your method and return null or whatever if some condition has not been met (recommended)
Also note that I'm assuming LelException extends RuntimeException, otherwise your catch statement won't compile.
Well it is up to you on how you will handle the situation.
If you are able to handle the exception by say logging it and just return null as most of the comments imply that is totally o.k.
Just consider that this situation could also mean that the method "returnLel" might not be the correct place to handle this exception but to let the caller decide what to do in this situation by "throwing it further" like so:
public String returnLel(String mattDamon) throws LelException{
trick(mattDamon); // The LelException could be thrown
return "lel";
}
This means if the caller calls your returnLel-Method he will have to try/catch the Exception (or throw it further up) and could in this case mean a better design because the caller will not receive null or a String' but aStringor aLeLException` instead
Move the return statement out of the try catch.
The try block should surround the part where an exception could be thrown, what the return statement not does.
Here the java tutorials for some basic knowledge about this topic:
The try Block
The catch Block
The finally Block