HOW to create a JUnit test involving throwing exceptions? - java

How to test an exception in the run function?
` public void run() {
ArrayBlockingQueue<String> bookQueue =
library.getBookQueue(book);
try {
bookQueue.take();
try {
updateState(State.IN_PROGRESS);
Thread.sleep(READ_TIME_MS);
bookQueue.put(book);
updateState(State.ENDED);
} catch(InterruptedException e){
bookQueue.put(book);
}
} catch(InterruptedException e) {
Thread.currentThread().interrupt();
}
finally {
updateState(State.ENDED);
}
}`

In the #Test annotation you can specify the expected exception
For Example
#Test(expected=IndexOutOfBoundsException.class)
public void outOfBounds() {
new ArrayList<Object>().get(1);
}
In the same way you can write test method and call run method inside of it
#Test(expected=Exception.class)
public void testRun() {
run();
}
We can also make this better by considering the #GhostCatsuggestions in the comments, you can addtry-catch` in test method
#Test
public void testRun() {
tyr {
run();
Asserts.fail(); //
}
catch(Exception ex) {
assertTrue(//some condition);
assertEquals(//some condition);
}
}
If run() method doesn't throw any exception test will fail because of Asserts.fail(), or in any exception case catch block assert statements will get executed

Related

Why would Java skip lines of code after method failure?

I've seen this behavior a few times lately. In the code below, why would execution jump to the finally block immediately after executing method2? I know method2 failed in some way, but I do know that neither method3 nor method4 are executed, instead jumping to method 5 in the finally block
try {
method1();
method2(); // fails
method3(); // not executed
} catch(Exception e) {
method4(); // not executed
} finally {
method5();
}
Hopefully you're clear on why method3() is not executing.
A possible reason that method4() would not execute is that method is throwing a Throwable that is not a subclass of Exception - most likely some kind of Error.
It is because the exception being thrown is not being caught by the type "Exception"
For example, an out of memory error.
public static void main(String[] args) {
try {
method1();
method2(); // fails
method3(); // not executed
} catch(Exception e) {
method4(); // not executed
} finally {
method5();
}
}
private static void method5() {
System.out.println("Done");
}
private static void method4() {
System.out.println("Hit");
}
private static void method3() {
}
private static void method2() {
throw new OutOfMemoryError();
}
private static void method1() {
}
You can catch error types by try {} catch (Throwable t) { }

Method under test calling private void method which I'd also like to include in my test

I've a JUnit which I want to use to test for exceptions. It's like this:
#Test
public void test1() throws Exception {
boolean testPass;
try {
method1();
testPass = true;
Assert.assertTrue(testPass);
}
catch(Exception e) {
testPass = false;
Assert.assertTrue(testPass);
}
System.out.println("End of test2 Junit");
}
method1() is like this:
public void method1() throws Exception {
try {
do something....
method2();
} catch (Exception e) {
throw e;
} finally {
do some more...
}
}
For what I want, my test is fine when just considering method1(). My problem is that method2() is called by method1() and can also throw an exception. It's like this:
private void method2() throws Exception {
if (confition is not met) {
do something...
throw new Exception();
} else {
do something else;
}
}
It's possible that no exception is thrown by method1() but then gets thrown by method2(). I'd like my test to check for an exception from either but I'm not sure how to factor method2() into my test, especially as it's a private void method. Can this be done and if so, how?
According to your code it is possible only if you can achieve true condition in this if:
if (condition is not met) {
do something...
throw new Exception();
} else {
do something else;
}
If for some reasons you couldn't prepare such kind of condition in the unit tests (say, Internet connection is needed) you may extract the condition checking into new method:
if (isNotCondition()) {
do something...
throw new Exception();
In the test class you override new method and return what you want:
MyService myService = new MyService() {
#Override
boolean isNotCondition() {
return true;
}
}
This is more compact way to test exceptional cases:
#Rule
public ExpectedException thrown = ExpectedException.none();
#Test
public void testMethod1WhenMethod2ThrowsException() throws Exception {
thrown.expect(Exception.class);
thrown.expectMessage("expected exception message");
myServive.method1();
}

Execute same piece of code in catch clause for all methods in a class

I have a class that has many methods. All the methods throw one exception when data is not ready. In that case, I want to retry the method after a certain interval. So in catch, I need to add retry logic. The same logic i need to add for all methods.
Is there some way/pattern to execute same logic for all catch clause without copy paste
One way I could think of is to write my own Exception class and Throw that exception. And do this retry logic from My Exception class.
Is there any other better way to this?
class MyClass {
public void method1() {
try {
//do some logic
} catch (Exception e) {
//retry logic
//existing exception handling logic
}
}
public void method2() {
try {
//do some logic
} catch (Exception e) {
//retry logic
//existing exception handling logic
}
}
public void method3() {
try {
//do some logic
} catch (Exception e) {
//retry logic
//existing exception handling logic
}
}
}
EDIT:
class MyClass {
public void method1(int a, int b) {
try {
//do some logic
} catch (Exception e) {
Object args[] = {a,b};
executeLater("method1",args);
//retry logic
//existing exception handling logic
}
}
public void method2() {
try {
//do some logic
} catch (Exception e) {
Object args[] = null;
executeLater("method1",args);
//retry logic
//existing exception handling logic
}
}
public void method3(String abcd, int a) {
try {
//do some logic
} catch (Exception e) {
Object args[] = {abcd,a};
executeLater("method1",args);
//retry logic
//existing exception handling logic
}
}
public boolean executeLater(String methodName, Object args[]){
//Execute given method with the supplied args
return true;
}
}
Added code that shows what i would be doing in each catch clause
boolean processCompleted=false;
while(!processCompleted){
try{
doProcess();
processCompleted=true;
}catch(Exception e){
Thread.sleep(10000);
}
}
This might give you an idea. It keeps try to call doProcess until it doesn't throw exception. If any exception occurs, waits 10 seconds.
Well, you could extract the whole catch block content to a method and call that one, but this only works if your retry logic is not dependent on the specific method. And it also requires a try-catch in every method.
Instead, use functional programming to shorten it:
public class Playground
{
public static void main(String[] args)
{
new Playground().method2(1, 2);
new Playground().method1();
}
public void method1()
{
tryAndTryAgain(() -> {
// logic 1
System.out.println("no params");
throw new RuntimeException();
});
}
public void method2(int a, int b)
{
tryAndTryAgain(() -> {
// logic 2
System.out.println(a + " " + b);
throw new RuntimeException();
});
}
public static void tryAndTryAgain(Runnable tryThis)
{
try
{
tryThis.run();
}
catch (Exception e)
{
new Timer().schedule(new TimerTask()
{
#Override
public void run()
{
tryAndTryAgain(tryThis);
}
}, 1000);
// existing exception handling logic
}
}
}
The exact structure depends on your specfic implementation, but it should give you an idea how to structure it. The benefit is that all those methods can concentrate on the business logic, and the retry logic and exception handling are done in a util method. And that util method doesn't even need to know anything about parameters, methods, or anything, because all the business logic is contained in the Runnable.

java.lang.NullPointerException and return code

I'm running some java binary from bash like:
run_me.sh
$JAVA_HOME/bin/java -Djava.library.path=path1/libs/opencv/lib -jar path2/bin/application.jar
echo "Exit code: "$?
but inside application I get java.lang.NullPointerException, howewer return code is 0, but I need some non zero exit code to understand from bash that application failed.
What is the proper way to handle such cases?
Update:
Here is an exxample of 'nested' try catch blocks, when I throw exception in inner_package_class return code is 0. So what is the proper way to get exception from inner_package_class.method1()?
public static void main(String[] args) {
try {
inner_package_class.method1();
System.out.printf("After inner method!\n");
} catch (Throwable t) {
System.exit(1);
}
}
public class inner_package_class {
public static void method1() {
System.out.printf("From inner method!\n");
try
{
throw new Exception("Some exception 2.");
} catch (Throwable t) {
}
}
}
Update 1:
This work as expected (return non zero exit code).
public class inner_package_class {
public static void method1() throws Exception {
System.out.printf("From inner method!\n");
throw new Exception("Some exception 2.");
}
}
You can add a try-catch-block around your main method and use
System.exit(1)
when you catch a Throwable
public static void main(String[] args) {
try {
... // your original code
} catch (Throwable t) {
// log the exception
t.printStacktrace(); // or use your logging framework
System.exit(1);
}
}
the return code is set by the exit method of System: by the way if, for instance, You want to return -1 in case of exception you can do as follow: in Your Main class you have to catch all throwable (so you will handle all possible case). here is an example
public static void main(String[] args) {
try { YOUR CODE
} catch(throwable t){
System.exit(-1);
}
System.exit(0);
}
the code show You how return -1 in case of exception and 0 in case of success.

How are timeouts handled in JUnit?

Say I have the following test:
#Test(timeout = 1)
public void test(){
while(true){}
}
This simulates a test that would take a long time to return, not from sleeping, but from raw calculation time. How does the test exit? If I create a thread and try the same thing, it does not compile.
public static void main(String[] args) {
Thread thread = new Thread() {
public void run() {
try {
while (true) {
}
} catch (InterruptedException e) {//Exception 'java.lang.InterruptedException' is never thrown in the corresponding try block'
e.printStackTrace();
}
}
};
thread.start();
thread.interrupt();
}
I can even attempt to replicate the implementation, but it still does not interrupt the thread:
public static void main(String[] args) {
Thread thread = new Thread() {
public void run() {
try {
doTest();
} catch (InterruptedException throwable) {
System.out.println("interrupted");
} catch (Throwable throwable) {
throwable.printStackTrace();
}
}
private void doTest() throws Throwable {
while (true) {
}
}
};
thread.start();
thread.interrupt();
}
The java.lang.Exception: test timed out after 1 milliseconds exception claims to be originating strait from the while loop when running the regular test.
I am confused as to how the test is 'interrupted', but I cannot do the same with a regular thread. How is this 'interrupting' feature implemented in JUnit?
The code tells you the truth: https://github.com/junit-team/junit/blob/master/src/main/java/org/junit/internal/runners/statements/FailOnTimeout.java

Categories