Alternate way to assert Exception thrown from private method in java - java

I need to assert that CustomException is thrown from one of the private utility method doSomething
This is what I implemented so far and is working.
Define rule at test class level
#Rule
public ExpectedException exception = ExpectedException.none();
Relevant part of test method
exception.expect(CustomException.class);
// prepare call to executePrivateMethod
try {
executePrivateMethod(objInstance, "doSomething",
arg0, arg1);
} catch (InvocationTargetException e) {
Assert.assertTrue("Invalid exception thrown",
(e.getCause() instanceof CustomException));
throw (CustomException) e.getCause();
}
Assert.fail("Invalid response");
I want to know if there is / are alternate / elegant way available to achieve this? P.S.: 1. Very helpful post but no mention of my scenario2. executePrivateMethod uses reflection to invoke private method

Your design is typical for when you need to do additional verification when an exception is thrown. The only comment I would make is that you don't need the fail, exception.expect takes care of that for you.
Also, you don't need to and should not cast to a CustomException. This could result in a ClassCastException instead of the nice error message stating expected CustomException, received SomeOtherException.

Related

JUnit exceptions handling testing

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());

Is it possible to monitor handled exceptions using JUnit?

This is what I have:
#Test
public testSendMessageToStub() {
// under the hood sends message
// if exception occurrs
// it will be catched and message will be put on retry
object.sendMessage();
}
Is there any way to mark test as failed if exception has occurred but was handled in catch block in the sendMessage() method?
Thanks
EDIT: It seems like I was too fixated on these legacy tests and how they were used, that totally missed the fact of sendMessage returning a response with a status code (!!!). So now I just assert status codes, can expand these tests into more detailed scenarios and spin them on jenkins. I would like to avoid to answer how these tests were checked previously. The thought to check for status codes came to me after reading Plux's answer. Thanks!
Exactly what you are looking for is not possible with JUnit as far as I know.
If you really would want to test this, you could store some information about the exception in the catch-block where it is handled in the sendMessage() method.
A better option, in my opinion, could be to test the output or state of the object. If the state/output is exactly the same as when an exception doesn't occur, then whats the point of testing it? Do you have an overly broad catch-block?
EDIT: To AdityaTS, I dont have enough reputation to comment on a post, but my comment: you have not supplied all the code, so I can not say for sure, but my guess is that its the Logger.getLogger IN the catch-block that casts the ClassNotFoundException. (Either that or loadConnectionInfo()) see http://docs.oracle.com/javase/7/docs/api/java/lang/ClassNotFoundException.html
You cannot do this without modifying sendMessage method. If for example you catch the exception there but choose to ignore it and just return some value, code outside of the method doesn't know it. You can get around this by refactoring the code of object: move the code that handles the exception to a separate method, called e.g. handleException. Then, in your test you can create a subclass where handleException will execute the original handleException from superclass, but additionally set some flag which you will be able to read in your test and in this way tell that the exception was thrown. However, if you cannot modify the code for object's class, I'm afraid you're out of luck.
So you expect the exception to propagate out of the sendMessage() method, right?
This is another way to write a test that verifies an exception you expect will be thrown.
#Test (expected = MyExpectedException.class)
public testSendMessageToStub() {
// under the hood sends message
// if exception occurrs
// it will be catched and message will be put on retry
object.sendMessage();
}
And it's usually best to be as specific as possible (e.g. MyExpectedException.class over Exception.class)
The exception generated in the sendMessage() class will be available in the test method. Add a try catch block around the sendMessage() method like this
#Test
public testSendMessageToStub() {
try
{
object.sendMehssage();
}
catch(Excpetion e) //Use more specific exception type if you know
{
fail(e.getMessage());
}
}
I have tried this in my code. It worked for me. Let me know.
public DBConnectionInfo connectionInit()
{
loadConnectionInfo();
try
{
Class.forName(dbObject.getDriver());
} catch (Exception e)
{
Logger lgr = Logger.getLogger(PostgreLocationManager.class.getName());
lgr.log(Level.SEVERE, e.getMessage(), e);
}
try
{
dbObject.setConnection(DriverManager.getConnection(dbObject.getDatabaseURL(), dbObject.getUserName(),
dbObject.getPassword()));
} catch (Exception e)
{
Logger lgr = Logger.getLogger(PostgreLocationManager.class.getName());
lgr.log(Level.SEVERE, e.getMessage(), e);
}
return dbObject;
}
The test case for the above class.
#Test
public void testDriverFailure()
{
when(dbModelObject.getDriver()).thenReturn("driver");
when(dbModelObject.getDatabaseURL()).thenReturn("jdbc:postgresql://127.0.0.1:5432/testdb");
when(dbModelObject.getUserName()).thenReturn("postgres");
when(dbModelObject.getPassword()).thenReturn("postgres");
try
{
dbConnector.connectionInit();
} catch (Exception e)
{
assertTrue(e instanceof ClassNotFoundException);
}
verify(dbModelObject).getDriver();
}

Wrap exceptions by runtime exceptions with an annotation

Is there a way to annotate a method so all exceptions thrown are converted to runtime exception automagically?
#MagicAnnotation
// no throws clause!
void foo()
{
throw new Exception("bar")'
}
Project Lombok's #SneakyThrows is probably what you are looking for. Is not really wrapping your exception (because it can be a problem in a lot of cases), it just doesn't throw an error during compilation.
#SneakyThrows
void foo() {
throw new Exception("bar")'
}
You can do this with AspectJ. You declare a joinpoint (in this case invocation of the method foo) and 'soften' the exception.
Edit To elaborate a bit on this:
Say you have the following class Bar:
public class Bar {
public void foo() throws Exception {
}
}
...and you have a test like this:
import junit.framework.TestCase;
public class BarTest extends TestCase {
public void testTestFoo() {
new Bar().foo();
}
}
Then obviously the test is not going to compile. It will give an error:
Unhandled exception type Exception BarTest.java(line 6)
Now to overcome this with AspectJ, you write a very simple aspect:
public aspect SoftenExceptionsInTestCode {
pointcut inTestCode() : execution(void *Test.test*());
declare soft : Exception : inTestCode();
}
The aspect basically says that any code from within a Test (i.e.: a method that starts with "test" in a class that ends in "Test" and returns 'void') that throws an exception should be accepted by the AspectJ compiler. If an exception occurs, it will be wrapped and thrown as a RuntimeException by the AspectJ compiler.
Indeed, if you run this test as part of an AspectJ project from within Eclipse (with AJDT installed) then the test will succeed, whereas without the aspect it won't even compile.
No way to do that, at least for now I use workaround like this (simplified):
#SuppressWarnings({"rawtypes", "unchecked"})
public class Unchecked {
public static interface UncheckedDefinitions{
InputStream openStream();
String readLine();
...
}
private static Class proxyClass = Proxy.getProxyClass(Unchecked.class.getClassLoader(), UncheckedDefinitions.class);
public static UncheckedDefinitions unchecked(final Object target){
try{
return (UncheckedDefinitions) proxyClass.getConstructor(InvocationHandler.class).newInstance(new InvocationHandler(){
#Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if (target instanceof Class){
return MethodUtils.invokeExactStaticMethod((Class) target, method.getName(), args);
}
return MethodUtils.invokeExactMethod(target, method.getName(), args);
}
});
}
catch(Exception e){
throw new RuntimeException(e);
}
}
}
And the usage looks like:
import static ....Unchecked.*;
...
Writer w = ...;
unchecked(w).write(str, off, len);
The trick is that interface is "never finished" and everytime I need unchecked method somewhere, I'll wrap that object into unchecked and let IDE generate method signature in interface.
Implementation is then generic (reflective and "slow" but usually fast enough)
There are some code post-processors and bytecode-weavers but this was not possible (not even aop or other jvm based language) for my current project, so this was "invented".
I think it is possible with bytecode re-engineering, customized compiler or perhaps aspect oriented programming1. In the contrary to Java, C# has only unchecked exceptions2.
May I ask why you want to suppress the checked exceptions?
1 according to Maarten Winkels this is possible.
2 and they are thinking about introducing checked ones, according to some Channel 9 videos.
Edit: For the question: It is possible in the sense that you can annotate your methods to flag them to be a candidate for checked exception suppression. Then you use some compile time or runtime trick to apply the actual suppression / wrapping.
However, as I don't see the environment around your case, wrapping an exception in these ways might confuse the clients of that method - they might not be prepared to deal with a RuntimeException. For example: the method throws an IOException and your clients catches it as FileNotFoundException to display an error dialog. However if you wrap your exception into a RuntimeException, the error dialog gets never shown and probably it kills the caller thread too. (IMHO).
The Checked exceptions are responsability of the method implementation.
Take very very carefully this fact. if you can do not use workaround artifacts like that.
You can do this in any case via use of the fact that Class.newInstance does not wrap an Exception thrown by the no-arg constructor in an InvocationTargetException; rather it throws it silently:
class ExUtil {
public static void throwSilent(Exception e) { //NOTICE NO THROWS CLAUSE
tl.set(e);
SilentThrower.class.newInstance(); //throws silently
}
private static ThreadLocal<Exception> tl = new ThreadLocal<Exception>();
private static class SilentThrower {
SilentThrower() throws Exception {
Exception e = tl.get();
tl.remove();
throw e;
}
}
}
Then you can use this utility anywhere:
ExUtil.throwSilent(new Exception());
//or
try {
ioMethod();
} catch (IOException e) { ExUtil.throwSilent(e); }
By the way, this is a really bad idea :-)
I use the completion / template system of Eclipse to wrap any block of code easily.
Here is my template :
try { // Wrapp exceptions
${line_selection}${cursor}
} catch (RuntimeException e) { // Forward runtime exception
throw e;
} catch (Exception e) { // Wrap into runtime exception
throw new RuntimeException(
"Exception wrapped in #${enclosing_method}",
e);
}

is there a way to both catch and throw an exception

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.

How safe is my safe rethrow?

(Late edit: This question will hopefully be obsolete when Java 7 comes, because of the "final rethrow" feature which seems like it will be added.)
Quite often, I find myself in situations looking like this:
do some initialization
try {
do some work
} catch any exception {
undo initialization
rethrow exception
}
In C# you can do it like this:
InitializeStuff();
try
{
DoSomeWork();
}
catch
{
UndoInitialize();
throw;
}
For Java, there's no good substitution, and since the proposal for improved exception handling was cut from Java 7, it looks like it'll take at best several years until we get something like it. Thus, I decided to roll my own:
(Edit: Half a year later, final rethrow is back, or so it seems.)
public final class Rethrow {
private Rethrow() { throw new AssertionError("uninstantiable"); }
/** Rethrows t if it is an unchecked exception. */
public static void unchecked(Throwable t) {
if (t instanceof Error)
throw (Error) t;
if (t instanceof RuntimeException)
throw (RuntimeException) t;
}
/** Rethrows t if it is an unchecked exception or an instance of E. */
public static <E extends Exception> void instanceOrUnchecked(
Class<E> exceptionClass, Throwable t) throws E, Error,
RuntimeException {
Rethrow.unchecked(t);
if (exceptionClass.isInstance(t))
throw exceptionClass.cast(t);
}
}
Typical usage:
public void doStuff() throws SomeException {
initializeStuff();
try {
doSomeWork();
} catch (Throwable t) {
undoInitialize();
Rethrow.instanceOrUnchecked(SomeException.class, t);
// We shouldn't get past the above line as only unchecked or
// SomeException exceptions are thrown in the try block, but
// we don't want to risk swallowing an error, so:
throw new SomeException("Unexpected exception", t);
}
private void doSomeWork() throws SomeException { ... }
}
It's a bit wordy, catching Throwable is usually frowned upon, I'm not really happy at using reflection just to rethrow an exception, and I always feel a bit uneasy writing "this will not happen" comments, but in practice it works well (or seems to, at least). What I wonder is:
Do I have any flaws in my rethrow helper methods? Some corner cases I've missed? (I know that the Throwable may have been caused by something so severe that my undoInitialize will fail, but that's OK.)
Has someone already invented this? I looked at Commons Lang's ExceptionUtils but that does other things.
Edit:
finally is not the droid I'm looking for. I'm only interested to do stuff when an exception is thrown.
Yes, I know catching Throwable is a big no-no, but I think it's the lesser evil here compared to having three catch clauses (for Error, RuntimeException and SomeException, respectively) with identical code.
Note that I'm not trying to suppress any errors - the idea is that any exceptions thrown in the try block will continue to bubble up through the call stack as soon as I've rewinded a few things.
There are a couple of way to handle this. The first is my preference if you don't need to know what the exception was.
boolean okay = false;
try {
// do some work which might throw an exception
okay = true;
} finally {
if (!okay) // do some clean up.
}
In some cases you can do the same without an extra variable, depending on what the try block does.
A second option is a hack but also works.
try {
// do some work which might throw an exception
} catch (Throwable t) {
// do something with t.
Thread.currentThread().stop(t);
}
The stop(Throwable t) method doesn't stop the thread, instead it causes the thread to throw the exception provided in an unchecked way.
You can use Unsafe.throwException() with a bit of fiddling and there is a way to do this with Generics which I have forgotten.
If you are that concerned about getting your uninitialization to happen then you may want to just put that code into a finally block, as, if it should be called at some point, then you perhaps should always clean up.
I am leery of catching Throwable as some of the exceptions I want to handle, and some I just log, as, there is no use passing exceptions that the user can't do anything about, such as a NullPointerException.
But, you didn't show what SomeException is defined as, but if an OutOfMemoryException is thrown, your throwable will catch it, but it may not be the same type as SomeException so your wrapper will be needed in your sample function, at least when I look at the instanceOrUnchecked method.
You may want to write a unit test, try different classes of Exceptions and see what does or doesn't work as expected, so you can document the expected behavior.
An alternative is to have a factory which creates SomeException only if the cause is a checked exception:
public static SomeException throwException(String message, Throwable cause) throws SomeException {
unchecked(cause); //calls the method you defined in the question.
throw new SomeException(message, cause);
}
The reason why I put in the return value in the method is so that the client can do something like this:
catch (Throwable e) {
undoInitialize();
throw SomeException.throwException("message", e);
}
so that the compiler is fooled into not requiring a return after the catch statement if the method has a return type, but it still throws the exception if the client forgot to put the throw before the call to the factory method.
The disadvantage of this over your code is that it is less portable (it works for SomeException, but not for SomeOtherException), but that may be ok, because it won't be for every exception type that you need to have an undo initialize.
If it fits your use case you could put the unchecked call in the constructor of SomeException and have the logic available to all subclasses, but that would have to fit your specific project - it would not be a good idea in the general case as it would prevent wrapping runtime exceptions.
public SomeException(message, cause) {
super(message, unchecked(cause));
}
private static Throwable unchecked(Throwable cause) {
if (cause instanceof Error) throw (Error) cause;
if (cause instanceof RuntimeException) throw (RuntimeException) cause;
return cause;
}

Categories