I'm running into an error of an unreported FileNotFoundException when trying to instantiate an object with a file in my test code. The class that I'm using/created has the FileNotFoundException in the constructor (only one constructor) so I'm not quite sure why I'm being asked for an additional FileNotFound when declaring an object.
//Constructor
public readFile(File file)throws FileNotFoundException {
//do i need to create a file object here?
Scanner inScanFile = new Scanner(file);
}
///////////Running Code from JUNIT below//////////////
public void Empty(){
File testFile = new File("HARRY_POTTER_TRIVIA.txt");
ReadingClass newReadtest = new ReadingClass(testFile); //Error occurs here
public readFile(File file)throws FileNotFoundException {
//do i need to create a file object here?
No, why? You already have one.
Scanner inScanFile = new Scanner(file);
This can throw FileNotFoundException, which is why this constructor has to either catch it or declare that it throws it, or one of its base classes.
}
///////////Running Code from JUNIT below//////////////
public void Empty(){
File testFile = new File("HARRY_POTTER_TRIVIA.txt");
ReadingClass newReadtest = new ReadingClass(testFile); //Error occurs here
That's because readFile() can throw FileNotFoundException, so, again, you have to either catch it or declare that you throw it, or one of its base classes.
Related
I have the following code that reads data from a csv file that I am trying to write a unit test for. I am unsure of how to go about it.
public class BudgetTags implements BudgetTagsList{
// State variables
private Set<String> tags = new TreeSet<>();
private String tag_file_path;
public BudgetTags(String tag_file_path){
//Retrieve tags from tag file
this.tag_file_path = tag_file_path;
this.retrieveTags();
}
public void retrieveTags() {
String line = "";
try{
// Begin reading each line
BufferedReader br = new BufferedReader(new FileReader(this.tag_file_path ));
while((line = br.readLine()) != null){
String[] row = line.split(",");
this.tags.add(row[0]); //Assume correct file format
}
br.close();
} catch (IOException e){
System.out.println("Fatal exception: "+ e.getMessage());
}
}
}
Note that the method retrieveTags(); is not allowing me to specify an additional FileNotFoundException since it extends IOException. It is being tested in the following manner:
#Test
#DisplayName("File name doesn't exist")
void testRetrieveTag3() {
String path = "test\\no_file.csv";
//Instantiate new tags object
BudgetTags tags = new BudgetTags(path);
IOException thrown = assertThrows(IOException.class, () -> tags.retrieveTags());
}
The variable path does not exist so I am expecting the test to catch the IOException, (although I would prefer a FileNotFoundException) . When I run this particular test, I receive an AssertionFailedError How can I restructure my test so that it catches the FileNotFoundException when a new tags object is instantiated, since retrieveTags() is called when a new tags object is generated?
The method retrieveTags() will not allow me to specify
The method is not actually throwing the exception but catching it. What you actually need to test is that your catch block gets executed. If all you want to do on catching the exception is printing the error, test system.out can help you assert the print statement
Your assertThrows test is failing becuase it's impossible for the constructor to throw an IOException. For one, it's a checked exception, which means both the constructor and the method would require a throws IOException clause. Second, you catch the exception; it's not thrown out of the method.
Based on your test, it should look more like this:
public class BudgetTags implements BudgetTagsList {
private final Set<String> tags = new TreeSet<>();
private String tagFilePath;
public BudgetTags(String tagFilePath) throws IOException {
this.tagFilePath = tagFilePath;
retrieveTags(); // can throw IOException
}
public void retrieveTags() throws IOException {
// note: use try-with-resources to handle closing the reader
try (BufferedReader br = new BufferedReader(new FileReader(tagFilePath))) {
String line;
while ((line = br.readLine()) != null) {
String row = line.split(",");
tags.add(row[0]);
}
}
// don't catch the exception; your test indicates you want it
// thrown out to the caller
}
}
class BudgetTagsTests {
#Test
#DisplayName("File does not exist")
void testRetrieveTags3() {
String tagFilePath = "test/no_file.csv";
// note: we need to test on the constructor call, because you call
// 'retrieveTags()' in it.
assertThrows(FileNotFoundException.class, () -> new BudgetTags(tagFilePath));
}
}
By passing FileNotFoundException.class, the test will fail if any other IOException is thrown.
You should not be catching the IOException the way you are, anyway. Yes, you log it, which means if you look at the logs you'll be aware that something went wrong. But other code won't know something went wrong. To that code, it will appear as if there were simply no tags in the file. By throwing the IOException out to the caller of retrieveTags(), you're letting the caller react to the exception as needed. And if the call succeeds, but the tags are empty, then it knows the file exists but simply had no tags.
Also, you say:
Note that the method retrieveTags(); is not allowing me to specify an additional FileNotFoundException since it extends IOException.
I'm not sure what exactly you tried from that statement, but it is possible to catch more specific exceptions even though you're also catching the more general exception. It's just that the order of the catch blocks matter:
try {
somethingThatThrowsIOException();
} catch (FileNotFoundException ex) {
// do something special for when the file doesn't exist
} catch (IOException ex) {
// handle general exception
}
The more specific exception must be caught before the more general exception.
Suppose you have some AppendObjectOutputStream class (which is an ObjectOutputStream!) which overrides writeStreamHeader() like this:
#Override
public void writeStreamHeader() throws IOException
{
reset();
}
Now also, let's say you plan on saving multiple objects to a file; one object for each time your program runs. Would you, even on the first run, use AppendObjectOutputStream()?
You have to write the stream header first time with regular ObjectOutputStream otherwise you will get java.io.StreamCorruptedException on opening the file with ObjectInputStream.
public class Test1 implements Serializable {
public static void main(String[] args) throws Exception {
ObjectOutputStream os1 = new ObjectOutputStream(new FileOutputStream("test"));
os1.writeObject(new Test1());
os1.close();
ObjectOutputStream os2 = new ObjectOutputStream(new FileOutputStream("test", true)) {
protected void writeStreamHeader() throws IOException {
reset();
}
};
os2.writeObject(new Test1());
os2.close();
ObjectInputStream is = new ObjectInputStream(new FileInputStream("test"));
System.out.println(is.readObject());
System.out.println(is.readObject());
The above did not work for me, specifically the reset() did not work.
I found the following here:
https://coderanch.com/t/583191/java/ObjectOutputStream-appending-file-overiding-ObjectOutputStream
#Override
protected void writeStreamHeader() throws IOException {
// TODO Auto-generated method stub
System.out.println("I am called");
super.writeStreamHeader();
}
This worked for me. I know it seems counter-intuitive and at first blush it seems like calling the superclass method should not do anything, but it does. Read the original post and try it.
ok this code was working earlier, but all of a sudden, java tells me that i can't reference the two stop objects (origin and destination) i'm trying to create in the loop from a static context, but i'm not referencing them, i'm creating a new temporary object every iteration, what am i missing here? this method is inside my public class.
the error just says: nonstatic variable cannot be referenced from a static context, where it says //problem areas
static void initializePassengers()
throws FileNotFoundException, IOException, NullPointerException
{
FileReader fr = new FileReader(pathto+"passengers.csv");
BufferedReader textReader = new BufferedReader(fr);
try {
while(!textReader.readLine().isEmpty()) {
String temp=textReader.readLine();
StringTokenizer te = new StringTokenizer(temp,",",false);
String name=te.nextToken();
Stop origin = new Stop(te.nextToken()); //problem area
Stop destination = new Stop(te.nextToken()); //problem area
allpassengers.add(new Passenger(name, origin, destination));
}
} catch(NullPointerException e){
System.out.println(e.getMessage());
}
textReader.close();
}
Since you are implying the problematic line is allpassengers.add(new Passenger(name, origin, destination)),
I'm assuming allpassengers are a non-static member. You should make it static in order to access it from a static method.
Suppose you have some AppendObjectOutputStream class (which is an ObjectOutputStream!) which overrides writeStreamHeader() like this:
#Override
public void writeStreamHeader() throws IOException
{
reset();
}
Now also, let's say you plan on saving multiple objects to a file; one object for each time your program runs. Would you, even on the first run, use AppendObjectOutputStream()?
You have to write the stream header first time with regular ObjectOutputStream otherwise you will get java.io.StreamCorruptedException on opening the file with ObjectInputStream.
public class Test1 implements Serializable {
public static void main(String[] args) throws Exception {
ObjectOutputStream os1 = new ObjectOutputStream(new FileOutputStream("test"));
os1.writeObject(new Test1());
os1.close();
ObjectOutputStream os2 = new ObjectOutputStream(new FileOutputStream("test", true)) {
protected void writeStreamHeader() throws IOException {
reset();
}
};
os2.writeObject(new Test1());
os2.close();
ObjectInputStream is = new ObjectInputStream(new FileInputStream("test"));
System.out.println(is.readObject());
System.out.println(is.readObject());
The above did not work for me, specifically the reset() did not work.
I found the following here:
https://coderanch.com/t/583191/java/ObjectOutputStream-appending-file-overiding-ObjectOutputStream
#Override
protected void writeStreamHeader() throws IOException {
// TODO Auto-generated method stub
System.out.println("I am called");
super.writeStreamHeader();
}
This worked for me. I know it seems counter-intuitive and at first blush it seems like calling the superclass method should not do anything, but it does. Read the original post and try it.
easy question is there an other function i can use instead of println, because i want to output a non-static variable to a file usig out.println();
This is my code:
import java.io.*;
public class main {
String outputString ="Math.sqrt(25);" ;
static String outputPath ="src/output.txt";
/**
* #param args
*/
public static void main(String[] args) throws IOException {
File f;
f= new File (outputPath);
//file creation
if(!f.exists()){
f.createNewFile();
System.out.println("File has been created");
}else{
f.delete();
System.out.println("1. File has been deleted");
f.createNewFile();
System.out.println("2. File has been created");
}
//adding string(text) to file
try{
FileWriter outFile = new FileWriter(args[0]);
PrintWriter out = new PrintWriter(outFile);
out.println(outputString);
out.close();
}catch(IOException e){
e.printStackTrace();
}
}
}
if that is not posible maybe there is an whole other way to go around it. my main problem is that i want to make a string in to peace of code. But that seem to be hard to do :) any help on that :)
The problem has nothing to do with println(). It has to do with the fact that, being non-static, outputString is associated with an instance of your class, and your code creates no such instance.
Either make outputString static, or create an instance of main:
public void doit(String[] args) throws IOException {
...
PrintWriter out = ...;
out.println(outputString);
...
}
public static void main(String[] args) throws IOException {
new main().doit(args);
}
The println function can print both static and non-static variables. The problem is that you're trying to access a non-static variable outputString from within a static context (your main method).
println is a non-static method of the PrintStream class. System, also a class, has a static member called out of type PrintStream which you can retrieve via the System.out call. This member is initialized when java is started.
Note that this does not in any way imply that this is anything other than a regular Object of type PrintStream, it's just that it's a singleton that is conveniently accessible statically from System.