I have a method that scans a file and assigns values to an object:
private List<Customer> customerList = new ArrayList<Customer>();
public void scanLocalFile() throws FileNotFoundException {
File file = new File("input.txt");
Scanner scan = new Scanner(file);
while (scan.hasNextLine()) {
String[] fields = line.split(";");
String name = fields[0];
String score = fields[1];
Customer customer = new Customer(name, score);
customerList.add(customer);
}
scan.close();
}
How do I write a junit test for a method like this? Is it possible to use the same file ("input.txt") for a unit test as well?
The file's structure:
John Smith;45;
Adam West;78;
CodePudding user response:
The basic approach to make this code unit-testable is to not hard-code the use of the input.txt
file.
Stultuske suggests passing in the File
as a parameter to the method, in order that you can then run the method for an arbitrary file during testing.
I'd go a step further than that and say: pass in a Reader
. Scanner
has a constructor which accepts a Reader
, and then you don't have to mess around with files during you unit test.
For example, you can construct a StringReader
with a hard-coded string that is the "file contents".
StringReader sr = new StringReader("John Smith;45;\nAdam West;78;");
Note, however, that if you pass in a Reader
, you shouldn't close the Scanner
at the end, because that will close the Reader
; and it is bad practice for code to close a Reader
(or Writer
or Input/OutputStream
; generally any resource) that it didn't open.
public void scanLocalFile(Reader r) {
Scanner scan = new Scanner(r);
while (scan.hasNextLine()) {
// ...
}
}
Actually, since you're just reading lines from the Scanner, I think it would be better to use BufferedReader
instead:
public void scanLocalFile(Reader r) {
new BufferedReader(r).lines()
.map(line -> {
String[] fields = line.split(";");
return new Customer(fields[0], fields[1]);
})
.forEach(customerList::add);
}