I runt into something strange. I have a method to read from a CSV file, line by line. The method takes the filePath and in my JUnit test, I'm testing this method with the wrong filePath expecting to get a FileNotFoundException. The thing is that JUnit5 doesn't throw that exception but in the eclipse console I can see that the JVM throws that exception, so I'm struggling to understand why
I've set up my test code to throw the exception but it doesn't get thrown. I tried to catch Exception but still no joy.
Here is the method and the test method
public void readData(String COMMA_DELIMITER, String READ_FILE_PATH) {
BufferedReader br = null;
try {
br = new BufferedReader(new FileReader(READ_FILE_PATH));
String line = "";
//Read to skip the header
br.readLine();
//Reading from the second line
while ((line = br.readLine()) != null)
{
String[] employeeDetails = line.split(COMMA_DELIMITER);
populateModel(employeeDetails);
}
//Lets print the Employee List
for(Employee e : empList)
{
System.out.println(e.getName() + "; " + e.getSurname() + "; " + e.getDateOfBirth() + "; " + e.getSex());
}
}
catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
catch (IOException e) {
e.printStackTrace();
}
}
#Test
void testWrongFilePath() {
String READ_FILE_PATH_WRONG = System.getProperty("user.dir") + "/teest/XXXFile.csv";
System.out.println(READ_FILE_PATH_WRONG);
Assertions.assertThrows(FileNotFoundException.class, () -> {
readData.readData(COMMA_DELIMITER, READ_FILE_PATH_WRONG);
});
}
In the console, I get the FIleNotFOundException, but the output of the test says that
org.opentest4j.AssertionFailedError: Expected java.io.FileNotFoundException to be thrown, but nothing was thrown.
You cannot expect from your Assertion framework to catch an exception that is caught inside your SUT:
catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
You either have to :
Log then rethrow same / different exception and assert on that.
Make your method return Boolean as a success equivalent which you can then assert on.
You're catching the FileNotFoundException within readData.
Try refactoring so that you don't have a try-catch, and have public void readData(String COMMA_DELIMITER, String READ_FILE_PATH) throws IOException { ...
(FileNotFoundException is a subclass of IOException.)
assertThrows(Class<T> expectedType, Executable executable)
doesn't assert that an exception is thrown at a time in your code (which is the true in your case). But that asserts that the statement invoked in the Executable lambda throws an exception (which is false in your case).
Since you caught the FileNotFoundException in the method under test, the exception is never propagates to the lambda return and JUnit can only emit an error because the expected exception was not encountered.
To assert such a thing, don't catch the exception by removing the catch statement and instead of declare throws FileNotFoundException in the declaration of the tested method :
public void readData(String COMMA_DELIMITER, String READ_FILE_PATH) throw FileNotFoundException {...}
Your method doesn't throw FileNotFoundException: you catch it, print the stack trace, and carry on as if no exception occurred:
catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
JUnit isn't magic: it can't detect things that happen inside the method, other than by detecting side effects (values returned, uncaught exceptions, mutating state).
Related
I'm try to figure out this for a while, so I have a method that is calling a count() method that is suppose to throw and exception
the count() method
public int count() throws ParseException {
return something that may throw the ParseException
}
and then calling from here
ParseQuery<ParseObject> query = ParseQuery.getQuery(className);
query.fromLocalDatastore();
int result = 0;
try {
result = query.count();
} catch (ParseException e) {
result = 0;
}
return result;
Now I have been trying different scenarios but no matter what the IDE still not compiling and give me the following error
Error:(254, 11) error: exception ParseException is never thrown in body of corresponding try statement
Error:(253, 33) error: unreported exception ParseException; must be caught or declared to be thrown
in the line result = query.count();
I have no idea what I'm doing wrong, thanks for any help
You cannot catch exception that will never thrown by your try block as error suggested
try {
result = query.count(); // this statement not throwing ParseException
} catch (ParseException e) { // you are trying to catch ParseException that never gonna throw.
result = 0;
}
It is like
try {
.... code // throws ExceptionA
}
catch (ExceptionB e) { // and calling ExceptionB
}
I am experimenting with exceptions and i want to ask when it is possible to handle multiple exceptions in one handler and when it is not?
For example i wrote the following code which combines two exceptions (FileNotFoundException OutOfMemoryError) and the program runs properly without any error. Al thought the handling is not so relevant with the functionality of the code i chose them just to see when i can combine multiple exceptions in on handler :
import java.io.FileNotFoundException;
import java.lang.OutOfMemoryError;
public class exceptionTest {
public static void main(String[] args) throws Exception {
int help = 5;
try {
foo(help);
} catch (FileNotFoundException | OutOfMemoryError e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public static boolean foo(int var) throws Exception {
if (var > 6)
throw new Exception("You variable bigger than 6");
else
return true;
}
}
But when i choose different type of exceptions the compiler gives me error . For example when i choose IOException and Exception i have the error the exception is already handled " :
import java.io.IOException;
import java.lang.Exception;
public class exceptionTest {
public static void main(String[] args) throws Exception {
int help = 5;
try {
foo(help);
} catch (IOException | Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public static boolean foo(int var) throws Exception {
if (var > 6)
throw new Exception("You variable bigger than 6");
else
return true;
}
}
So why is this happening ? Why in one occasion i can use multiple exception in handler and in the other not ? Thank you in advance.
You are getting the message because IOException is a subclass of Exception. Therefore, if an IOException were thrown, it would be caught by a catch (Exception e) statement, so catching it as an IOException is redundant.
The first example works because neither FileNotFoundException nor OutOfMemoryError is a subclass the other.
However, you can catch sub-classed exceptions using the separate catch statement:
try{
// code that might throw IOException or another Exception
} catch (IOException e) {
// code here will execute if an IOException is thrown
} catch (Exception e) {
// code here will execute with an Exception that is not an IOException
}
If you do this, please note that the subclass must come first.
I'm trying to write a test case for the method setTrailer() within the class ErParser. setTrailer() has try-catch clauses, and in one of its catch clauses, it catches NullPointerException. I'm trying to write a Junit test for the case where setTrailer() throws and catches a NullPointerException, but the test case keeps failing. Is it because I already caught the exception in the method itself? Should I be catching the exception in the test case instead?
The test case:
public class TestERParser {
#Test(expected=NullPointerException.class)
public void nullSetTrailer() {
ERParser recCurrParse = new ERParser();
recCurrParse.setTrailer(null);
}
}
setTrailer() method within the ERParser Class:
public class ERParser {
private static final String TRAILER_E = "GRAND TOTAL";
private static final String TRAILER_R = "TRAILER";
public String trailerRecord;
/**
* Constructs an ERParser object.
*/
public ERParser() {
this.trailerRecord = null;
this.trailerVals = null;
}
/**
* Populates the trailerRecord field with the summary (trailer) record of the input file.
* #param file Input file
* #throws NullPointerException, FileNotFoundException, IOException
*/
public void setTrailer(File file) {
try {
FileReader fReader = new FileReader(file);
BufferedReader bReader = new BufferedReader (fReader);
String currLine = new String();
readLoop:
while (bReader.ready()) {
currLine = bReader.readLine();
if (currLine.contains(TRAILER_E) || currLine.contains(TRAILER_R)) {
break readLoop;
}
}
this.trailerRecord = currLine.trim();
System.out.println("From setTrailer(): " + this.trailerRecord);
fReader.close();
bReader.close();
} catch (NullPointerException exception) {
exception.printStackTrace();
} catch (FileNotFoundException exception) {
exception.printStackTrace();
} catch (IOException exception) {
exception.printStackTrace();
}
}
}
As you suspected you are catching the NPE inside of your code and it is not being propagated. If you expected your users to catch this exception you should remove this code and adorn your method with throws, to the appropiate classes.
public void setTrailer(File file) throws Exception {
FileReader fReader = new FileReader(file);
BufferedReader bReader = new BufferedReader (fReader);
String currLine = new String();
readLoop:
while (bReader.ready()) {
currLine = bReader.readLine();
if (currLine.contains(TRAILER_E) || currLine.contains(TRAILER_R)) {
break readLoop;
}
}
this.trailerRecord = currLine.trim();
System.out.println("From setTrailer(): " + this.trailerRecord);
fReader.close();
bReader.close();
}
As your code now throws a checked Exception, you will need to update your Junit method slightly, to catch the checked exceptions
#Test(expected=NullPointerException.class)
public void nullSetTrailer() throws Exception {
ERParser recCurrParse = new ERParser();
recCurrParse.setTrailer(null);
}
We can argue about whether or not this catch block means the exception is handled. I would argue that merely printing the stack trace is not handling anything. It might be better to add a throws clause to the method signature and let clients decide what to do with exceptions.
If the method is written that way, it's up to you to test it as-written. You wouldn't have a choice if this was a 3rd party library.
Write the test that throws the exception; succes means trailerRecord is set to null.
Your code has another flaw: close the streams in a finally block. You risk not closing the input stream properly as written.
In your test case are expecting a NullPointerException class. If you catch it, the caller class will not get it. Hence, either you can remove the try/catch blocks or you can rethrow the exception after printing stacktrace :
catch (NullPointerException exception) {
exception.printStackTrace();
throw new NullPointerException();
}
In Main function, after a try_block throws an exception the function is supposed to be break. My question is how can I make it keep on executing to the next try_block. Below I'm giving an example:
public static void main(String [] s){
ABC aBC = new ABC();
try {
aBC.execute();
} catch (Exception e) {
_log.error(ErrorCodeEnum.ERROR,
"XXXXXXX!!! in " + new Date(),e);
}
BCD bCD = new BCD();
try {
bCD.execute();
} catch (Exception e) {
_log.error(ErrorCodeEnum.ERROR,
"YYYYYYYYYYY!!! in " + new Date(),e);
}
}
The code should work as it stands - i.e. the second block should still get executed if the first block throws and catches an Exception.
However you might want to consider catching Throwable rather than Exception if you truly want to catch everything. In particular, java.lang.Error is not a subclass of Exception, but is a subclass of Throwable.
Just to be sure, you can wrap the statements you want executed in a finally block as follows:
ABC aBC = new ABC();
try
{
aBC.execute();
}
catch (Exception e)
{
_log.error(ErrorCodeEnum.ERROR, "XXXXXXX!!! in " + new Date(), e);
}
finally
{
BCD bCD = new BCD();
try
{
bCD.execute();
}
catch (Exception e)
{
_log.error(ErrorCodeEnum.ERROR, "YYYYYYYYYYY!!! in " + new Date(), e);
}
}
The statements in the finally block will get executed regardless if an exception occurs in the outer try block.
I am new to testing with JUnit and I need a hint on testing Exceptions.
I have a simple method that throws an exception if it gets an empty input string:
public SumarniVzorec( String sumarniVzorec) throws IOException
{
if (sumarniVzorec == "")
{
IOException emptyString = new IOException("The input string is empty");
throw emptyString;
}
I want to test that the exception is actually thrown if the argument is an empty string. For that, I use following code:
#Test(expected=IOException.class)
public void testEmptyString()
{
try
{
SumarniVzorec test = new SumarniVzorec( "");
}
catch (IOException e)
{ // Error
e.printStackTrace();
}
The result is that the exception is thrown, but the test fails.
What am I missing?
Thank you, Tomas
Remove try-catch block. JUnit will receive exception and handle it appropriately (consider test successful, according to your annotation). And if you supress exception, there's no way of knowing for JUnit if it was thrown.
#Test(expected=IOException.class)
public void testEmptyString() throws IOException {
new SumarniVzorec( "");
}
Also, dr jerry rightfully points out that you can't compare strings with == operator. Use equals method (or string.length == 0)
http://junit.sourceforge.net/doc/cookbook/cookbook.htm (see 'Expected Exceptions' part)
maybe sumarniVzorec.equals("") instead of sumarniVzorec == ""
how about :
#Test
public void testEmptyString()
{
try
{
SumarniVzorec test = new SumarniVzorec( "");
org.junit.Assert.fail();
}
catch (IOException e)
{ // Error
e.printStackTrace();
}
Another way to do this is :
public void testEmptyString()
{
try
{
SumarniVzorec test = new SumarniVzorec( "");
assertTrue(false);
}
catch (IOException e)
{
assertTrue(true);
}