Junit Test case of method that already has a try-catch clause - java

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

Related

Junit not catching FileNotFoundException

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).

File Scanner: Unreported exception FileNotFoundException; must be caught or declared to be thrown

I have tried everything I can find on the internet, and nothing seems to fix this. I am begging for help, tell me what I am doing wrong. I am brand new to Java. Thanks!
import java.util.Scanner;
class File_Scanner {
public static void read() {
File credentials_file = new File("credentials.txt");
Scanner file_reader = new Scanner(credentials_file);
String[] users = new String[6];
int index_counter = 0;
try {
while (file_reader.hasNextLine()) {
users[index_counter] = file_reader.nextLine();
}
file_reader.close();
} catch (Exception e) {
System.out.println(e.getClass());
}
}
}
This is showing the following error
Unreported exception FileNotFoundException; must be caught or declared to be thrown
I would like to recommend to surround the whole read function with a try/catch block like the following.
import java.util.Scanner;
class File_Scanner{
public static void read(){
try {
File credentials_file = new File("credentials.txt");
Scanner file_reader = new Scanner(credentials_file);
String[] users = new String[6];
int index_counter = 0;
while (file_reader.hasNextLine()) {
users[index_counter] = file_reader.nextLine();
}
file_reader.close();
} catch (Exception e) {
System.out.println(e.getClass());
}
}
}
The idea of try/catch is to avoid any error that might occur while running your program. In your case, Scanner file_reader = new Scanner(credentials_file); can throw an error if the credentials_file is not found or deleted. Hence you need to cover this around a try block which will give you an exception which can be handled to show proper response message in the catch block.
Hope that helps!
I agree with the other answers as to the problem (the Scanner can throw an exception if it can't find the file). I haven't seen what I'd consider the correct solution though.
String[] users = new String[6];
int index_counter = 0;
File credentials_file = new File("credentials.txt");
try (Scanner file_reader = new Scanner(credentials_file)) {
while (file_reader.hasNextLine()) {
users[index_counter] = file_reader.nextLine();
index_counter++;
}
} catch (FileNotFoundException e) {
// handle exception
} catch (NoSuchElementException e) {
// handle exception
} catch (IllegalStateException e) {
// handle exception
}
The try-with-resources statement will automatically close the Scanner for you. This will work with any class that implements the AutoCloseable interface.
And in this case, it puts the statement within the scope of the try, so exceptions will be caught.
Your exception handling is questionable, so I didn't include it. But that's not really the point here. You can read more about Best Practices to Handle Exceptions in Java or How to Specify and Handle Exceptions in Java.
There is an argument that you should let the exception bubble up to the caller. This answer describes how to do that. But in this case, the caller doesn't really know how to handle a FileNotFoundException, because it doesn't know anything about the file. The file is defined in this method.
You could throw a different, more explanatory exception. Or you could handle the exception here by explaining what a credentials.txt is. Or fail over to a default. Or just log the exception, although that's questionable. If you do that, you should explain (in a comment) why that is sufficient.
I added a line to increment index_counter just because it seemed to be missing.
See also
Why do I get "Exception; must be caught or declared to be thrown" when I try to compile my Java code?
Am I using the Java 7 try-with-resources correctly?
Java has checked exceptions. Which means that if the code within your method declares that it might possibly throw a particular exception, your method either needs to do one of the following:
Either (1) handle that exception:
public static void read() {
try {
// your method code
} catch (FileNotFoundException ex) {
// handle the exception
}
}
Or (2) declare that it might possibly throw that exception:
public static void read() throws FileNotFoundException {
// your method code
}
Just add this to your method declaration:
public static void read() throws FileNotFoundException
For ways to handle checked exceptions in java check this(Oracle Docs Java Tutorials):
You associate exception handlers with a try block by providing one or
more catch blocks directly after the try block. No code can be between
the end of the try block and the beginning of the first catch block.
try {
} catch (ExceptionType name) {
} catch (ExceptionType name) {
}
And this:
Sometimes, it's
appropriate for code to catch exceptions that can occur within it. In
other cases, however, it's better to let a method further up the call
stack handle the exception
public void writeList() throws IOException {
P.S. Also, it has been already discussed on stackoverflow, so maybe should be marked as duplicate.
You should read the java checked exception
public static void read() {
try {
File credentials_file = new File("credentials.txt");
Scanner file_reader;
file_reader = new Scanner(credentials_file);
String[] users = new String[6];
int index_counter = 0;
while (file_reader.hasNextLine()) {
users[index_counter] = file_reader.nextLine();
}
file_reader.close();
} catch (FileNotFoundException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} catch (Exception e) {
System.out.println(e.getClass());
}
}

Using custom exception in Java

I am trying to throw my custom exception in java but currently I have had no luck. I have two classes a readWrite class which allows the user to enter the file name and a text to be wrote to the file (via the constructor). It has three methods, write, read and a writeToFile which validates if the file ends in .txt if it does now it should throw my custom exception class stating that "Sorry but this system only accepts .txt files" which I have created in a toString() method in my custom exception. I can not seem to make it work, below is the code, some might be able to help, I hope I have explained properly as I am new to Java, note I have commented out some code as I was trying a few different things to make it work
ReadWrite.java
import java.io.*;
public class ReadWrite
{
private final String file;
private final String text;
public ReadWrite(String file, String text)
{
// initialise instance variables
this.file=file;
this.text=text;
}
private void write() //throws InvalidFileException
{
try {
FileWriter writer = new FileWriter(file);
writer.write(text);
writer.write('\n');
writer.close();
}
catch(IOException e)
{
System.out.print(e);
}
}
public boolean writeToFile()
{
boolean ok;
try{
FileWriter writer = new FileWriter(file);
{
if(file.toLowerCase().endsWith(".txt"))
{
write();
ok = true;
} //if end
else{
ok=false;
//throw new InvalidFileException();
} //else end
}
} //try end
catch(IOException e) {
ok=false;
} // catch end
//catch (InvalidFileException e){
//System.out.println(e.toString());
//}
return ok;
}
public void read(String fileToRead)
{
try {
BufferedReader reader = new BufferedReader(new FileReader(fileToRead));
String line = reader.readLine();
while(line != null) {
System.out.println(line);
line = reader.readLine();
}// while end
reader.close();
}//try end
catch(FileNotFoundException e) {
System.out.println(fileToRead + " the system can not find the file specified");
} //catch end
catch(IOException e) {
e.printStackTrace();
} //catch end
}
}
InvalidFileException.java
import java.io.FileNotFoundException;
import java.io.*;
public class InvalidFileException extends Exception
{
/**
* Constructor for objects of class InvalidFileException
*/
public InvalidFileException(String message)
{
super(message);
}
public String toString()
{
return ("Sorry but this system only accepts .txt files");
}
}
try this:
private void write() throws InvalidFileException {
try {
if(!file.getName().endsWith(".txt") {
throw new InvalidFileException(".txt files only.");
}
FileWriter writer = new FileWriter(file);
writer.write(text);
writer.write('\n');
writer.close();
}
catch(IOException e)
{
// handle exception please.
}
Please note, that you have to override the "getMessage()" Method of Exception in order to print your custom message. Or set it in the super() call.
Overriding the toString() method makes your super() call and therefore your custom (detail) message passed to the exception (in my example ".txt files only.") obsolete, because this string won't be printed anymore.
Below is your requirement:
it does not it should throw my custom exception class stating that
"Sorry but this system only accepts .txt files"
I think you got confused because of toString. You really don't need that toString method. You correctly implemented a InvalidFileException which accepts a String argument.
So, now all you need is throw new InvalidFileException("Sorry but this system only accepts .txt files"); or use whatever String message you want while throwing InvalidFileException.
Please note, if you are throwing an exception from a method and catching it in same method looks illogical unless you are doing because APM (application performance monitoring) tools logging purpose.
As other note, if you are throwing exception like this then you need to add a throw statement in your method signature indicating that this method "may" throw so-and-so exception. So, that called of that method can either re-throw or catch it.
If you are catching the exception somewhere then use getMessage method on the exception object and you will get same message as you placed while throwing the exception, in this case - "Sorry but this system only accepts .txt files"
InvalidFileException extends Exception but you only ever try to catch IOException and FileNotFoundException. I think you meant to have InvalidFileException extend IOException.

Creating Custom Exception

I am using this link as a reference for creating custom exceptions. For my class practice, if no file is selected or passed in, my custom UnknownFileException should occur, but when I go and run my driver and put in an invalid filename I get a nullpointerexception instead?
My driver which has Adventure adventure = new Adventure(args[0]).
My custom exception:
import java.io.FileNotFoundException;
public class UnknownFileException extends FileNotFoundException {
public UnknownFileException() {
super("We couldn't tell what file this is");
}
public UnknownFileException(String message) {
super(message);
}
}
Code:
public class practice {
public String[] array;
public String line;
public PrintWriter outputStream = null;
public Scanner inputStream = null;
public practice(String fileName) throws UnknownFileException {
array = new String[100];
try {
inputStream = new Scanner(new FileReader(fileName));
line = inputStream.nextLine();
array[0] = line;
for (int i = 1; i < array.length; i++) {
array[i] = inputStream.nextLine();
}
outputStream = new PrintWriter(new
FileOutputStream("newFile.txt"));
} catch(UnknownFileException e) {
System.out.println(e.getMessage());
} catch (FileNotFoundException e) {
throw new UnknownFileException(e.getMessage());
} finally {
inputStream.close();
}
}
}
You probably got a stack trace, which should have pointed you to the line throwing the NullPointerException. I'm guessing it was this line:
inputStream.close();
The problem is that if you put in an invalid file name, new Scanner(new FileReader(fileName)) will throw, and inputStream will never be assigned. Because you have a finally block, however, before it throws your custom exception, it will try to execute the finally. But this gives a NullPointerException because inputStream is null, and that exception takes precedence, I believe (I'd have to check the language rules to make sure of what happens in this case).
Fix your finally block to test whether inputStream is null.
More: It's ยง14.20.2 of the JLS. This is pretty complicated, but basically if any exception is thrown from the finally block, any earlier exception thrown or caught is discarded.
inputstream is still null
Make the following change:
} finally {
if (inputStream != null) {
inputStream.close();
}
}
or use try-with-resources instead.

Error "unreported exception java.io.ioexception must be caught or declared to be thrown" in Java class

I am getting a "unreported exception java.io.ioexception must be caught or declared to be thrown" for some reason. I throw an I/O exception in this method:
private void setChar() throws IOException
{
try
{
int data = in.read();
if(data==-1)
{
eof = true;
}
else
{
currentChar = (char) data;
}
}
catch (IOException e)
{
System.exit(0);
}
}
And I call the method here (in the constructors):
private BufferedReader in;
private char currentChar;
private boolean done;
public Scanner(InputStream inStream)
{
in = new BufferedReader(new InputStreamReader(inStream));
done = false;
getNextChar();
}
public Scanner(String inString)
{
in = new BufferedReader(new StringReader(inString));
done = false;
setChar();
}
Am I calling / throwing the exception wrong?
Your Scanner constructor can throw an IOException, because it's calling setChar(), and that can throw it.
You must either declare your constructor as throwing the exception, or catch the exception in your constructor and deal with it.
setChar(); in your constructor throws an IOException.
Therefore, you must catch it in your constructor, or your constructor have to throw an IOException as well.
However, you don't even need to add throws IOException after the declaration of the setChar() method since you are catching potential exceptions inside it.
Your setChar() method says that it can throw an IOException, but your second constructor does not handle it.
You either need to change the setChar() methods signature to not throw the exception (as, in fact, it doesn't throw an IOException), or get you constructor to handle it, for example ...
public Scanner(String inString)
{
in = new BufferedReader(new StringReader(inString));
done = false;
try {
setChar();
}
catch (IOException ie){
System.exit(1)
}
}

Categories

Resources