I have a method that is going to the DB so all our JDBC stuff in the DAO method is inside a try/catch block. It is catching SQLException
When I write a test case against this method and if a SqlException occurs then my testcase does not say 'caused an error'. it just goes on its merry way.
However, If I dont catch the SqlException in the DAO method but add throws SqlException to the method instead then my test case says 'caused an error' and shows me the error that happened. (this is what I want).
When I try adding throws SqlException along with the method catching the SqlException then also my test case does not say 'caused an error'.
what is the way around it? one is to have try/catch block inside my test case but even if I do this my Junit test case does not say 'caused an error' though the exception IS posted to standard output.
...but besides that anything else?
My IDE is Netbeans. this is where I run the test cases.
Code:
public class MyDaoClass {
Connection con;
public MyDaoClass (Connection connection)
{
this.con = connection;
}
public SomeObject someMethod (String id)
{
try{
Connection con = this.con;
CallableStatement cs = con.prepareCall("{call some_sp_name (?)}");
cs.setString (1, id);
cs.execute()//imagine an error happens here
ResultSet rs = cs.getResultSet()
...
....
//return SomeObject...
}
catch (SqlException e) //If I remove this and add 'throws SQLException to method then everything is ok
{
log.error(e.getMessage());//i dont have access to log object in test case
}
}
}
public class MyTestSuite extends TestCase
{
//populate local connection
public void testSomeMethod () throws SQLException
{
MyDaoClass myd = new MyDaoClass(connection);
SomeObject s = myd.someMethod("blah");
assertEquals (s.getFirstName(), "pepe");
}
}
All checked exceptions in Java must be declared in the method specification. SqlException is a checked exception, so if you want to throw it, you must include it in the specification.
If you want to throw an exception, but you can't change the method specification, you need to use an unchecked exception, like RuntimeException. It will also cause JUnit to show the error that happened.
The Java Tutorials: Exceptions is an excellent reference on this topic.
If you add throws SQLException to the method, then you don't have to try-catch it anymore.
And yes, you can catch and throw an exception:
try {
// some code
}
catch (SomeException e) {
throw e;
// or,
// throw new SomeOtherException();
}
JUnit doesn't care what you write to standard output. If the exception leaks out of your method, then JUnit takes notice.
If you catch the exception inside your method, then it's correct behavior for the exception not to come out of your method, because it was (we hope!) handled there. So a passing test is a Good Thing.
What you should be testing for is whether your method is producing the correct result (whatever that may be) even in circumstances when an exception is thrown (and handled).
that is not the full code is it? the compiler would complain that someMethod is not always returning a value.
If you want to keep the method as is, then at least add "return null;" after the try/catch.
That way, if an SQLException occurs, then assertEquals should throw NullPointerException which should work on your TestCase.
Side advice, i would check if connection is not null before using it.
Instead of re-throwing the exception, you can also return a null reference instead of an empty or incomplete object. Your callers must check for null's and handle the case when the DAO fails to load the object.
Alternatively, you can stub the log object in your JUnit test and inject it into the DAO via an alternative constructor. Your stubbed logger subclass can deliver the message to your test for inspection.
In addition to what Chip Uni said above re: Runtime exceptions to not need to be declared,
you should also note that exceptions can be nested, i.e.
catch (SqlException e)
{
throw new RuntimeException(e);
}
This will throw a RuntimeException that contains an SqlExceotion.
Related
I am having trouble understanding how precise rethrow works in Java 7 and later versions. As pointed out in https://www.theserverside.com/tutorial/OCPJP-Use-more-precise-rethrow-in-exceptions-Objective-Java-7, in Java 7 and later versions we can use the throws clause, in a method declaration, with a comma-separated list of specific exceptions that the method could throw. If all these exceptions are subtypes of the general exception java.lang.Exception, we will be able to catch any of them in a catch block that catches this supertype, while letting client code (eg. a caller method) to know which of the possible subtypes exceptions actually occurred.
Initially, I thought that in order to let know client code which exception actually occurred, we needed to specify the list of specific exceptions in the throws clause. Nevertheless, in the following example the client code (the main() method) seems able to retrieve that information, even if we only specify the exception java.lang.Exception in the throws clause of the called method. Therefore, my question is:
Why the following code outputs the same, regardless of whether the throws clause of the method runException() is throws ExceptionA, ExceptionB or throws Exception ?
I am using Oracle JVM-12 in Eclipse. Thanks in advance!
class ExceptionA extends Exception{}
class ExceptionB extends Exception{}
public class RethrowingAndTypeChecking{
public static void runException(char what) throws Exception{
//public static void runException(char what) throws ExceptionA, ExceptionB{
try{
if(what == 'A')
throw new ExceptionA();
else if (what == 'B')
throw new ExceptionB();
}
catch(Exception e){
throw e;
}
}
public static void main (String args[]){
char ch;
for (int i=0;i<2;i++) {
if(i==0) ch='A';
else ch = 'B';
try{
runException(ch);
}
catch(ExceptionA e){
System.out.print("In main(), 'catch(ExceptionA e){}', caught exception: " + e.getClass());
}
catch(ExceptionB e){
System.out.print("In main(), 'catch(ExceptionB e){}', caught exception: " + e.getClass());
}
catch(Exception e){
System.out.print("In main(), 'catch(Exception e){}', caught exception: " + e.getClass());
}
System.out.println();
}
}
}
output:
In main(), 'catch(ExceptionA e){}', caught exception: class ExceptionA
In main(), 'catch(ExceptionB e){}', caught exception: class ExceptionB
What you're missing is the case where you need to handle those possible exceptions in different ways. Your code is catching individual exceptions, but it is, roughly speaking, performing the same action.
If you were to handle ExceptionA in a considerably different way from how you handle ExceptionB, then catching the broad Exception would not allow you to do that specifically:
catch(Exception e){
// something unexpected happened
// e could be an ExceptionA problem
// e could be an ExceptionB problem
// e could be any other unchecked exception
}
When the catch(Exception e){} block is entered, the exception could pretty much be anything, but you have only one generic code block to handle it.
Beside this, if the method you're calling declares specific checked exceptions, then the compiler can help you handle only those exceptions, thus adding to the predictability of the code
try{
runException(ch);
} catch(ExceptionA e){
// code specific to handling ExceptionA problems
} catch(ExceptionB e){
// code specific to handling ExceptionB problems
} catch(ExceptionC e){ //will not compile, because not declared by runException
// code specific to handling ExceptionB problems
}
Quoting #Carlos Heuberger, my code outputs the same, regardless of whether the throws clause of the method runException() is throws ExceptionA, ExceptionB or throws Exception because:
the run-time type of the exception is used to select the catch clause: see 14.20.1. Execution of try - catch
Whatever the exception reference type (in this case ExceptionA, ExceptionB or Exception) used to refer to the exception object thrown by method runException(), such method will throw objects of type either ExceptionA or ExceptionB. These objects will be assignment compatible with the catch parameters of the first two catch of the main() method.
After paragraphs 8.4.6, 11.2.3 and 14.20.1 of the Java Language Specification, I understood that what we actually specify in a throws clause of a method signature is the list of the exception reference types that will be assignment compatible with any possible exception object thrown from the method (given a class reference type we can make it point to instance objects of itself or to instance objects of its subclasses, not superclasses ). That tells any other caller method what exceptions it may have to deal with when invoking the method with the throws clause. In my code example, the advantage of using the clause throws ExceptionA, ExceptionB is that I will not need to catch java.lang.Exception in the main(). In fact, if I choose clause throws Exception in method runException() and delete the cath(Exception) block from the main() I will get a compile-time error. This is because even if we will be throwing ExceptionA or ExceptionB objects at run-time, the compiler will understand that method runException() may throw out an exception object of type Exception, which will not be assignment compatible with any of the catch parameters in the main() (Exception is a superclass of both ExceptionA and ExceptionB).
It's because, you've been throwing the Subclasses at,
try{
if(what == 'A')
throw new ExceptionA();
else if (what == 'B')
throw new ExceptionB();
}
of "Exception class" which are in turn being thrown out at,
catch(Exception e){
throw e;
}
after being assigned to "Exception class( at Exception e)", it will not make a difference if you specify throwing a Superclass type throws objectReference at
public static void runException(char what) throws Exception){
or Subclass type throws objectReferences at
public static void runException(char what) throws ExceptionA, ExceptionB){
As java compiler allows you to specify a throws ObjectReference, if it is of a Superclass of the object being thrown at the try statement.
These throws declarations are so that you list more explicitly what happens out of the method. Otherwise this is ordinary polymorphism: you use base class to combine in multiple subclasses, however you are definitely not changing the instances, this is why at runtime in both cases the exceptions are resolved to their concrete classes.
As a rule, you should never catch (Exception ex). Because this will catch RuntimeExceptions too. It sometimes makes sense to catch (Throwable t) or to use Thread.setDefaultUncaughtExceptionHandler to customize your uncaught exception handler to catch exceptions and then display them to the user. Sometimes I will catch an Exception, wrap it in a RuntimeException (or an Error) and throw that
When it comes to exceptions, you should really only be catching them when you can do something with them, or when you want to make sure that an exception doesn't cause the rest of the method to not process.
Personally I divide exceptions into 3 types
Problems in your code: This is something for you to fix
Problems with the user: For instance if you tell them to enter a number and they enter 'a', that's the user's error
"Friend" Exceptions: SocketException, for instance, is an example of this. If the socket closes and you have a thread waiting on input on it, it will throw this Exception, releasing the thread and letting you do clean-up on the socket.
I am trying to test the next exception, but I don't know how to throw the exception from JUnit, because is a internal exception of the method.
public boolean suscribirADato(int idDato) {
InetAddress ip = null;
boolean adecuadamenteSuscrito = false;
try {
ip = InetAddress.getByName(ipMulticast.get(idDato));
grupoMulticast.set(idDato, ip);
conexion.joinGroup(grupoMulticast.get(idDato));
adecuadamenteSuscrito = true;
} catch (IOException e) {
LOGGER.info(e.getMessage());
}
return adecuadamenteSuscrito;
}
Other replied that you should use a mocking framework.
However, my understanding of your question is the following:
I don't know how to throw the exception from JUnit, because is a
internal exception of the method.
What I understand is that you are trying to unit-test an exception thrown and caught inside the method ?
Perhaps your method should be divided into 2 or more methods, which you can test separately ?
From your code sample, the logic being executed when the exception is thrown is
LOGGER.info(e.getMessage());
You may also choose to mock LOGGER and keep a trace when info is called. Then, you can assert that LOGGER.info was indeed called (If I understood correctly, that is).
You need to look into the Mockito framework. http://mockito.org/ when(myMockedObject.routine(anyParameter())).thenThrow(new NullPointerException());
What is the point of catching and then also throwing an Exception like below? Is it bad practice to do both?
try{
//something
} catch (Exception e){
throw new RuntimeException("reason for exception");
}
Usually, such code is used to re-wrap exceptions, that means transforming the type of the exception. Typically, you do this when you are limited in what exceptions are allowed out of your method, but internally other types of exceptions can happen. For example:
class MyServiceImplementaiton implements MyService {
void myService() throws MyServiceException { // cannot change the throws clause here
try {
.... // Do something
} catch(IOException e) {
// re-wrap the received IOException as MyServiceException
throw new MyServiceException(e);
}
}
}
This idiom enables to keep propagating exceptions to the caller, while conforming to the throws clause in the interface and hide the details of the internals (the fact that IOExceptions can happen).
In practice, this is always better than just calling e.printStackTrace() which will actually "swallow" the error condition and let the rest of the program run as if nothing had happened. In this respect, behaviour of Eclipse is quite bad as it tends to auto-write such bad-practice constructs if the developer is not careful.
This is called rethrowing an exception, and it is a common pattern.
It allows you to change the class of the exception (such as in this case), or to add more information (also the case here, as long as that error string is meaningful).
It is often a good idea to attach the original exception:
throw new RuntimeException("cause of the problem", e);
Rethrowing as an unchecked exception (a RuntimeException) is sometimes necessary when you still want to throw an exception, but the API of your method does not allow a checked exception.
In your example, an Exception is caught and a RuntimeException is thrown, which effectively replaces a (potentially) checked exception with an unchecked exception that doesn't have to be handled by the caller, nor declared by the throwing method in a throws clause.
Some examples :
This code passes compilation :
public void SomeMethod ()
{
try {
//something
} catch (Exception e){
throw new RuntimeException("reason for exception");
}
}
This code doesn't pass compilation (assuming "something" may throw a checked exception) :
public void SomeMethod ()
{
//something
}
An alternative to catching the Exception and throwing an unchecked exception (i.e. RuntimeException) is to add a throws clause :
public void SomeMethod () throws Exception
{
//something
}
This is one use case of catching one type of exception and throwing another. Another use case is to catch one type of exception and throw another type of checked exception (that your method declares in its throws clause). It is sometimes done in order to group multiple exceptions that may be thrown inside a method, and only throw one type of exception to the caller of the method (which makes it easier for them to write the exception handling code, and makes sense if all those exceptions should be handled in the same manner).
I have this unit test, that the overall test fails because of the exceptions that is thrown, although its expected:
#Test(expected = AutoGenerateStringIdException.class)
public void testPut_shouldThrowException(){
RootEntity rootObject = new RootEntity();
// Some codes here
try {
Key key = store.put(rootObject);
} catch(AutoGenerateStringIdException e){
assertEquals(e.getMessage(), "Cannot auto-generate String #Id");
}
}
You can either have #Test(expected = SomeException.class) or use a try...catch as you're doing. You can't use both of them at the same time.
When you declare a test to expect a certain exception to be thrown and if you catch it within the test, it wouldn't be thrown, would it?
Although I haven't tried it, you could try re-throwing the exception from the catch block.
catch(AutoGenerateStringIdException e){
assertEquals(e.getMessage(), "Cannot auto-generate String #Id");
throw e;
}
Please have a look at the JUnit wiki: https://github.com/junit-team/junit/wiki/Exception-testing It lists different approaches for testing exceptions.
If exception is expected in test, you should not catch it. Just remove try/catch and watch, what happens.
public void foo() {
begin();
try {
...
commit();
} catch (Exception e) {
rollback();
throw e;
}
}
In the sample above, there is an error because foo has no throws Exception. Adding that wouldn't make do the method's usability a lot of good either.
What's the best way to do this? How do you do something if an error occurs without really "handling" the error?
Since Java 8 we use
/**
* Cast a CheckedException as an unchecked one.
*
* #param throwable to cast
* #param <T> the type of the Throwable
* #return this method will never return a Throwable instance, it will just throw it.
* #throws T the throwable as an unchecked throwable
*/
#SuppressWarnings("unchecked")
public static <T extends Throwable> RuntimeException rethrow(Throwable throwable) throws T {
throw (T) throwable; // rely on vacuous cast
}
You can rethrow a checked exception, but only by avoiding the compilers checked exception validation.
public void foo() throws MyCheckedException {
begin();
try {
...
commit();
} catch (Exception e) {
rollback();
// same as throwing an exception without the compiler knowing.
Thread.currentThread().stop(e);
}
}
Before you use stop() you should read http://download.oracle.com/javase/6/docs/technotes/guides/concurrency/threadPrimitiveDeprecation.html
Thread.currentThread().stop(e) .. is behaviorally identical to Java's throw operation, but circumvents the compiler's attempts to guarantee that the calling method has declared all of the checked exceptions that it may throw:
At least two approaches come to mind, which are usually going to be combined depending on what you want foo to do:
1. Catch and rethrow only the relevant exceptions
There are only so many exceptions the code in your main flow can throw (probably mostly SqlExceptions). So only catch and rethrow those, and declare that you're doing so. More to the point, rethrow only the ones you're not actually handling (in your simplified sample code, you're not handling any, but your real life code is probably more subtle).
Mind you, some of the exceptions may be runtime exceptions, and so you may want to combine this with the below.
2. Don't catch the exception at all
Like this:
// Signature changes to include any exceptions that really can be thrown
public void foo() throws XYZException, ABCException {
// A flag indicating that the commit succeeded
boolean done = false;
begin();
try {
// Don't have any `return` statements in here (or if you do,
// set `done` to `true` first)
...
commit();
done = true; // Commit didn't throw an exception, we're done
} finally {
// finally clause always happens regardless
if (!done) {
// We must be processing an exception; rollback
try {
rollback();
} catch (Exception e) {
// quash it (e.g., leave this block empty), we don't want
// to mask the real exception by throwing a different one
}
}
}
}
Naturally your signature needs to include any exceptions that may be thrown in the main flow, but that's what you're trying to do, if I'm understanding you correctly.
Again, you may well combine these two approaches, because you may want to handle some exceptions and not others.
Wrap it with some RuntimeException which is unchecked.
Adding that wouldn't make do the method's usability a lot of good either.
No. It will be good at documentation, also caller will take care handling it.
Also See
exception-thrown-inside-catch-block-will-it-be-caught-again
throws-or-try-catch
I'd say that in this case rolling back is handling the exception appropriately. It's one of the few cases where it's legitimate to catch and re-throw.
Simply catching and logging an exception is not what I would consider handling. Rather than rethrowing, in that case I'd rather see checked exceptions added to the method signature and let it bubble up.
you may throw a subclass of RuntimeException - they don't require a catch()
the key point is, why should you throw a new Exception from a catch block.
if you use catch then handle your exception there in your catch. If you have to inform the caller method with an exception, then don't catch the exception with try-catch, instead, sign your method with throws and let the caller catch the e xception.
or throw a RuntimeException, i find this idea less useful because of lack of readability, then you don't need to sign your method with throws.
Here you've chanced on one of the biggest religious schisms in the Java, ( if not wider ) , world. It boils down to those that feel, as TJ seems to, and I do too, that checked exceptions are valuable for many reasons, VS the Rod Johnson/Spring school that in the design of Java, checked exceptions were used in many instances where they shouldn't, say closing a resultset or socket, so because it was wrongly used in many cases, it makes them useless so all exceptions should be unchecked. There are many classes in the Spring framework that are very thin wrappers around standard Java objects, but convert checked exceptions to unchecked. It drives me berserk!
Anyway, put me down as strongly agreeing with everything TJ has said, but know that you'll probably never find a "right" answer.
It's worth mentioning some advances in this area.
First, in Java 7, it's possible to catch and throw generic exceptions, as long as what's declared inside the try block is caught or declared in the outer block. So this would compile:
void test() throws SQLException {
try {
conn.commit();
} catch (Throwable t) {
// do something
throw t;
}
}
This is well explained here : http://docs.oracle.com/javase/7/docs/technotes/guides/language/catch-multiple.html
Another way is described here : http://blog.jooq.org/2012/09/14/throw-checked-exceptions-like-runtime-exceptions-in-java/
The reason you may want to use that has often to do with lambdas, or throwing exceptions from some generic methods. I ran into this when I wanted to replace repeating constructs of:
try {
do_operation
flag_success
} catch (Throwable e) {
flag_error
throw e;
}
With using a method of:
public static void wrapExec(RunnableT s) {
try {
s.run();
flag_success
} catch (Throwable t) {
flag_error
doThrow(t);
}
}
and therefore replacing the whole try/catch block with just
wrapExec(()->{do_operation})