java junit exception hadling for code coverage - java

I am new to java, Junit and jacoco. I am doing exception handling as below. I am catching Exception class as well in case the method throws any other exception that were missed to catch earlier.
private void myMethod1() throws MyCustomException {
....
try {
..... straight JDBC calls for select, insert, update operations ....
} catch (SQLException sqEx) {
logger.error(....);
new MyCustomException(.....);
} catch (RuntimeException rEx) {
logger.error(....);
new MyCustomException(.....);
} catch (Exception ex) {
logger.error(....);
new MyCustomException(.....);
}
}
in Junit test, tried below. When I have runtime any exception I throw is always going to RuntimeException catch block itself unless I throw Exception. which other checked exception can I try so it goes into Exception catch block. Due to this I am unable to get the code coverage needed.
private void testMyMethod1() {
....
try {
.....
when(...).thenThrow(new SocketException());
spy.myMethod1();
} catch (SQLException sqEx) {
assertTrue(false);
} catch (RuntimeException rEx) {
assertTrue(false)
} catch (Exception ex) {
assertTrue(true);
}
}
your help is appreciated.

In thenThrow you have throwed socket exception,but you are trying to catch some other exception like SQLException. If the exception thrown is not a child of SQLException then it won't come into that block.
Also please make sure you are creating proper exception inside when()..thenThrow() statement by debugging.Sometimes creating inappropriate exception will cause problems.

A few things... if your myMethod1() is not in the same java class, you can't test a private method in a separate unit test class. Its best to make your myMethod1() package protected. In your test class, its also best not to have any try catch or if statements inside it. You must make separate test methods per test case, not all in one. You can take advantage of #Rule or #expected annotations. I recommend doing something like this...
#Test(expected = MyCustomException.class)
public void testMyMethod1_handlesSQLException(){
doThrow(SQLException.class).when(...);
Foo foo = new Foo();
foo.myMethod1();
}
#Test(expected = MyCustomException.class)
public void testMyMethod1_handlesRuntimeException(){
doThrow(RuntimeException.class).when(...);
Foo foo = new Foo();
foo.myMethod1();
}
#Test(expected = MyCustomException.class)
public void testMyMethod1_handlesException(){
doThrow(Exception.class).when(...);
Foo foo = new Foo();
foo.myMethod1();
}

In JUnit 5, a possible way would be:
#ParameterizedTest
#ValueSource(classes = {
SQLException.class,
RunTimeException.class,
Exception.class
})
void methodWrapsException(Exception toBeWrapped) {
Foo foo = new Foo(...);
doThrow(toBeWrapped).when(...);
assertThrows(MyCustomException.class, () -> foo.myMethod1());
}
This makes use of JUnit 5 support for parameterized classes and its lambda-based assertions for exceptions.

Related

Mockito catch exception in void method

I have this method:
public void deleteTableEsiti() throws Exception {
try{
EsitiDAO esitiDAO = new EsitiDAO();
int deletedEsiti = esitiDAO.deleteTableEsiti(em);
}
catch(Exception e ){
log.error(e);
}
finally{
em.close();
}
}
I'm trying to make the test that cover the catch exception. I have tried many times but I can't cover that lines with Mockito.
This is the test that i have write:
#Test(expected=Exception.class)
public void mockException(){
ServiceG service = Mockito.mock(ServiceG.class);
try {
Mockito.doThrow(Exception.class).when(service).deleteTableEsiti();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
};
//Mockito.when(service.deleteTableEsiti()).thenThrow(new Exception());
}
I have always this error:
[ERROR] Failures:
[ERROR] JUnit.mockException Expected exception: java.lang.Exception
and lines are not covered by test.
Firstly, your method deleteTableEsiti() never throws any exception. It catches it and logs it, but always returns normally. If you want your method to throw an exception, don't catch it, or catch it and throw a custom exception that wraps the original exception.
Your unit test does not actually call the mocked method deleteTableEsiti() anyway, since all it does is set up a mock rule to throw an exception when the method is called (which you never call).
So, after calling Mockito.when, you should call (or do something that calls) that method in your unit test.

Should I always use Lambda Expressions for Exception Tests?

I always tested my exceptions with annotations.
#Test (expected = Exception.class)
public void test1() {
methodToTest() // throws an exception
}
I finally switched to Java 8, and I came across lambda Expressions. Now there is another option to get the desired result.
#Test
public void test2() {
assertThrows(Exception.class, () -> methodToTest());
}
public static <X extends Throwable> Throwable assertThrows(
final Class<X> exceptionClass, final Runnable block) {
try {
block.run();
} catch(Throwable ex) {
if (exceptionClass.isInstance(ex))
return ex;
}
fail("Failed to throw expected exception");
return null;
}
I understand that with the second version you can check for single methods more precisely, and you don't have to worry about other methods within a single test that could throw the expected exception as well. Furthermore, with an "assertThrows" method, all tests can have the same structure, because it all comes down to a call for an assertion.
Besides those two points, are there any pro arguments for the new way? For me, it feels like its still superior to go with the annotations, as long as I am only testing a single method within a single test.
You missed a third way, the ExpectedException jUnit rule:
public class SimpleExpectedExceptionTest {
#Rule
public ExpectedException thrown= ExpectedException.none();
#Test
public void myMethod_throws_no_exception_when_passed_greeting() {
fixture.myMethod("hello");
}
#Test
public void myMethod_throws_MyException_when_passed_farewell() {
thrown.expect(MyException.class);
fixture.myMethod("goodbye");
}
}
I find this clearer than the #Test (expected = ...) version, since the expectation goes closer to the method call.
There is also the plain old Java version, which we used to make do with:
try {
fixture.myMethod("should throw");
fail("Expected an exception");
} catch (MyException e) {
// expected
}
Which of the many is "better" depends entirely on context. Don't adopt one universally. Pick the one that gives you the clearest test in a given situation.
When you begin coding non-test code in a lambda-centric style, it is likely that you'll find yourself wanting to use the lambda-centric assertThrows().
If all you want to test is that an exception is thrown, the first syntax is better. It is standard, it is concise, and it prevents you from writing the same ugly try-catch over and over.
You could have a test slightly more complicated where you want to assert that an exception is thrown and some method is not called. In this case, manually catching the exception is reasonable.
#Test
public void test1() {
DBClient dbClient = spy(new DBClient());
try {
new Server().doRequest(new InvalidRequest(), dbClient);
fail("should have thrown");
} catch (InvalidRequestException e) {
verify(dbClient, times(0)).query(any(Query.class));
}
}
Regarding the use on lambdas more specifically, it's up to you. Just note that Runnable cannot throw checked exceptions so you would need something like
#FunctionalInterface
public interface ThrowingRunnable<E extends Exception> {
void run() throws E;
}
I don't see a problem with either approach--there is no right or wrong in matters of style; just use the one that best suits each situation. I suggest that assertThrows should also check for thrown exceptions that aren't of the expected type, and, as #Dici suggests, that a functional interface that allows checked exceptions be used:
public static <X extends Throwable> Throwable assertThrows(
final Class<X> exceptionClass, final CheckedRunnable block) {
try {
block.run();
} catch(Throwable ex) {
if (exceptionClass.isInstance(ex)) {
return ex;
} else {
throw new AssertionError("Unexpected exception was thrown", ex);
}
}
fail("Failed to throw expected exception");
}
#FunctionalInterface
public interface CheckedRunnable<R extends RuntimeException> {
void run () throws Exception;
}

Java with Groovy handling of closures throwing Exceptions

We have a system that is possible to customise using groovy scripts and I've spotted a very strange effect on the type of exceptions throw from these scripts.
We have a groovy script with the following:
process {
throw new Exception("weeee")
}
Process is defined as a Closure in the base class of the script:
public abstract class ScriptBaseClass extends Script {
Closure process;
public void process( Closure code ) {
process = (Closure) code.clone();
}
}
In the Java class that actually runs the scripts we have the following method (omitted all the set up code as it doesn't seem relevant):
public void process() {
try {
script.process.call();
} catch (Exception e) {
logger.debug("exception thrown from groovy script", e);
throw e;
}
}
Note the process method here doesn't declare it throws any exceptions. However it quite clearly re-throws the Exception e that it caught. This code is valid, it compiles and runs quite happily. It throws the Exception as I wanted.
Does any one know how this is legal code? In theory I shouldn't be able to throw a checked exception out of a method that doesn't declare that it throws it.
It works because Java compiler (starting since Java 7) can determine re-thrown exception. For catch (Exception e) it thinks it's RuntimeException because there were no other (checked) exception declared in call().
You can read about it there, for example: https://docs.oracle.com/javase/7/docs/technotes/guides/language/catch-multiple.html
So this code compiles perfectly:
public void xxxxx() {
try {
System.out.println('Hi!'); //or anything else w/o declared exceptions
} catch (Exception e) {
throw e;
}
}
Java compiled sees that only RuntimeException could be caught here, so it doesn't ask you do declare anything.
But for this:
public void xxxxx() {
try {
throw new IOException(); //or anything that have declared checked exception
} catch (Exception e) {
throw e;
}
}
it will fail to compile, because IOException could be caught and re-thrown
Introducing closures or anything Groovy related is unnecessary complexity. The following is valid Java code:
public class Demo {
public void someMethod() {
try {
System.out.println("Hello");
} catch (Exception e) {
throw e;
}
}
}
Note that the following is not valid and will not compile:
import java.sql.*;
public class Demo {
public void someMethod() {
try {
Connection c = DriverManager.getConnection("", "", "");
} catch (SQLException e) {
throw e;
}
}
}
Groovy and the JVM don't really care about an exception being a checked one or not. Only the Java compiler cares about this here. In fact you can use the catch on any RuntimeException or its parent classes (of which Exception is one) without requiring it being declared as thrown from something called in the try-block. So it is fine by the compiler to catch Exception or Throwable even. Of course, from a program logic view it is an entirely different matter.

How to assert that a void function will throw a exception?

Our test code uses assert.
So is there any functions in assert class that can expect that a void function throws an exception?
#Test(expected=MyCustomException.class)
public void testBlahBlah_BlahBlah(){
voidMethodThatThrowsException();
}
This annotation of JUnit is what you are looking for.
Two ways I accomplish this:
First way is if I want to make sure an exception is thrown but not fail the test for it and I want to continue asserting.
try {
myObject.methodThatShouldThrowAnException("baddata");
assert.fail("Exception should have been thrown");
catch (SomeException e) { }
assert.equals(anotherMethod(), "hello");
The second way is if I don't want to do additional asserts (This is JUnit, could vary for the test framework you are using...TestNG has similar syntax):
#Test(expected = SomeException.class)
public void myTest() {
myObject.methodThatShouldThrowAnException("baddata");
}
Most testing frameworks (notably JUnit) will allow you to specify an exception class, so that the test will fail if an exception is not thrown.
If you can't use this method, then you can just wrap it in a try/catch and do the assertion in the catch block.
Ex (using JUnit):
#Test(expected=SomeException.class)
public void testSomeFunction_expectedSomeException(){
MyClass clazz = new MyClass();
clazz.someMethodThatThrowsTheException();
fail("shouldn't have gotten here...");
}
Or:
//#Test -- this annotation may or may not be supported by your framework
public void testSomeFunction_expectedSomeException(){
MyClass clazz = new MyClass();
try {
clazz.someMethodThatThrowsTheException();
fail("shouldn't have gotten here...");
}
catch (SomeException ex) {
// assert...
}
catch (Exception ex) {
fail("Some other exception occurred, also not good");
}
}

Java 8: How do I work with exception throwing methods in streams?

Suppose I have a class and a method
class A {
void foo() throws Exception() {
...
}
}
Now I would like to call foo for each instance of A delivered by a stream like:
void bar() throws Exception {
Stream<A> as = ...
as.forEach(a -> a.foo());
}
Question: How do I properly handle the exception? The code does not compile on my machine because I do not handle the possible exceptions that can be thrown by foo(). The throws Exception of bar seems to be useless here. Why is that?
You need to wrap your method call into another one, where you do not throw checked exceptions. You can still throw anything that is a subclass of RuntimeException.
A normal wrapping idiom is something like:
private void safeFoo(final A a) {
try {
a.foo();
} catch (Exception ex) {
throw new RuntimeException(ex);
}
}
(Supertype exception Exception is only used as example, never try to catch it yourself)
Then you can call it with: as.forEach(this::safeFoo).
If all you want is to invoke foo, and you prefer to propagate the exception as is (without wrapping), you can also just use Java's for loop instead (after turning the Stream into an Iterable with some trickery):
for (A a : (Iterable<A>) as::iterator) {
a.foo();
}
This is, at least, what I do in my JUnit tests, where I don't want to go through the trouble of wrapping my checked exceptions (and in fact prefer my tests to throw the unwrapped original ones)
This question may be a little old, but because I think the "right" answer here is only one way which can lead to some issues hidden Issues later in your code. Even if there is a little Controversy, Checked Exceptions exist for a reason.
The most elegant way in my opinion can you find was given by Misha here Aggregate runtime exceptions in Java 8 streams
by just performing the actions in "futures". So you can run all the working parts and collect not working Exceptions as a single one. Otherwise you could collect them all in a List and process them later.
A similar approach comes from Benji Weber. He suggests to create an own type to collect working and not working parts.
Depending on what you really want to achieve a simple mapping between the input values and Output Values occurred Exceptions may also work for you.
If you don't like any of these ways consider using (depending on the Original Exception) at least an own exception.
You might want to do one of the following:
propagate checked exception,
wrap it and propagate unchecked exception, or
catch the exception and stop propagation.
Several libraries let you do that easily. Example below is written using my NoException library.
// Propagate checked exception
as.forEach(Exceptions.sneak().consumer(A::foo));
// Wrap and propagate unchecked exception
as.forEach(Exceptions.wrap().consumer(A::foo));
as.forEach(Exceptions.wrap(MyUncheckedException::new).consumer(A::foo));
// Catch the exception and stop propagation (using logging handler for example)
as.forEach(Exceptions.log().consumer(Exceptions.sneak().consumer(A::foo)));
I suggest to use Google Guava Throwables class
propagate(Throwable throwable)
Propagates throwable as-is if it is an
instance of RuntimeException or Error, or else as a last resort, wraps
it in a RuntimeException and then propagates.**
void bar() {
Stream<A> as = ...
as.forEach(a -> {
try {
a.foo()
} catch(Exception e) {
throw Throwables.propagate(e);
}
});
}
UPDATE:
Now that it is deprecated use:
void bar() {
Stream<A> as = ...
as.forEach(a -> {
try {
a.foo()
} catch(Exception e) {
Throwables.throwIfUnchecked(e);
throw new RuntimeException(e);
}
});
}
You can wrap and unwrap exceptions this way.
class A {
void foo() throws Exception {
throw new Exception();
}
};
interface Task {
void run() throws Exception;
}
static class TaskException extends RuntimeException {
private static final long serialVersionUID = 1L;
public TaskException(Exception e) {
super(e);
}
}
void bar() throws Exception {
Stream<A> as = Stream.generate(()->new A());
try {
as.forEach(a -> wrapException(() -> a.foo())); // or a::foo instead of () -> a.foo()
} catch (TaskException e) {
throw (Exception)e.getCause();
}
}
static void wrapException(Task task) {
try {
task.run();
} catch (Exception e) {
throw new TaskException(e);
}
}
More readable way:
class A {
void foo() throws MyException() {
...
}
}
Just hide it in a RuntimeException to get it past forEach()
void bar() throws MyException {
Stream<A> as = ...
try {
as.forEach(a -> {
try {
a.foo();
} catch(MyException e) {
throw new RuntimeException(e);
}
});
} catch(RuntimeException e) {
throw (MyException) e.getCause();
}
}
Although at this point I won't hold against someone if they say skip the streams and go with a for loop, unless:
you're not creating your stream using Collection.stream(), i.e. not straight forward translation to a for loop.
you're trying to use parallelstream()

Categories