Good practice with Mockito And BufferedReader - java

I'm trying to test a class that makes File/Stream treatment. For instance, the method readFile will use BufferedReader to return an ArrayList of String with every lines of the file inside:
public ArrayList<String> readFile(String fileName)
{
ArrayList<String> result = new ArrayList<String>();
FileReader fr = null;
BufferedReader br = null;
try {
fr = new FileReader(STORAGE_DIRECTORY+fileName);
br = new BufferedReader(fr);
String sCurrentLine;
while ((sCurrentLine = br.readLine()) != null) {
result.add(sCurrentLine);
}
}
catch (FileNotFoundException e) {
return new ArrayList<String>();
} catch (IOException e) {
return new ArrayList<String>();
}
br.close();
fr.close();
return result;
}
But when I use Mockito in order to mock bufferedReader method "readLine()",a FileNotFoundException is thrown because of FileReader constructor. Must I use temporaryFile or Mock FileReader constructor ?
#Test
public void readFileTest5() throws Exception {
BufferedReader bufferedReader = Mockito.mock(BufferedReader.class);
FileReader fileReader = Mockito.mock(FileReader.class);
when(BufferedReader.readLine()).thenReturn("abc");
assertEquals("",new ArrayList<String>(), FileUtil.readFile("abc"));
}
Thank you

In readFile BufferedReader wraps FileReader and FileReader is created inside that method so you have no opportunity to mock FileReader which means that you have no way to mock the inputs into your BufferedReader instance.
This approach makes testing difficult.
I'd suggest changing your approach. For example:
public ArrayList<String> readFile(BufferedReader reader) {
// ...
}
Then your test could be:
#Test
public void readFileTest() throws Exception {
BufferedReader bufferedReader = Mockito.mock(BufferedReader.class);
Mockito.when(bufferedReader.readLine()).thenReturn("a", "b", "c", null);
List<String> expected = Arrays.asList("a", "b", "c");
Assert.assertEquals("", expected, readFile(bufferedReader));
}
Or without Mockito at all:
#Test
public void readFileTest() throws Exception {
BufferedReader bufferedReader = new BufferedReader(new StringReader("a\nb\nc"));
List<String> expected = Arrays.asList("a", "b", "c");
Assert.assertEquals("", expected, readFile(bufferedReader));
}
Another approach would be to create an actual file and read it i.e. no need for mocking anything. You could use JUnit's Temporary Folder Rule to help clean up after the test.
On a separate note: the readFile() isn't closing the BufferedReader and FileReader safely.

Since your FileUtil does read a file referenced by name, you do need to create a file in the file system. This is easily done by
File tempFile = File.createTempFile("temp", ".tmp");
tempFile.deleteOnExit(true);
some words on your implementation code:
ArrayList<String> result = new ArrayList<String>();
// combine directory and file name like this
File f = new File(STORAGE_DIRECTORY, fileName);
// use try-with-resource here, like this:
try (BufferedReader br = new BufferedReader(new FileReader(f))) {
String sCurrentLine;
while ((sCurrentLine = br.readLine()) != null) {
result.add(sCurrentLine);
}
} catch (FileNotFoundException e) {
// no need to create a new list
return Collections.emptyList()
} catch (IOException e) {
return Collections.emptyList()
}
// you don't need to close the reader if you use try-with-resource
return result;
}
You can of course just use Files#readAllLines.
try {
return Files.readAllLines(Paths.get(STORAGE_DIRECTORY, fileName), StandardCharsets.UTF-8);
} catch (IOException e) {
return Collections.emptyList();
}

Related

Spring Boot - Throwing IOException when mocking BufferedReader

I am currently trying to test a service in Spring Boot. It should read a file from a BufferedReader. The first test works just fine, but the one where I try to mock the IOException is not.
HTMLService:
#MockBean
HTMLService htmlService;
public String read(String fileName, String username) {
String s = null;
String filePath = new File("").getAbsolutePath();
String path = filePath+"/src/main/resources/html/"+fileName;
try (BufferedReader br = new BufferedReader(new FileReader(path))) {
String line = br.readLine();
StringBuilder sb = new StringBuilder();
while (line != null) {
sb.append(line).append("\n");
line = br.readLine();
}
s = sb.toString();
} catch (IOException e) {
e.printStackTrace();
}
s = s.replace("KINO-USERNAME", username);
return s;
}
Test:
#Test
void testReadException() {
when(htmlService.read("Registration.html", "DrBackmischung")).thenReturn("Test");
try {
BufferedReader br = Mockito.mock(BufferedReader.class);
when(br.readLine()).thenThrow(IOException.class);
} catch (IOException e) {
e.printStackTrace();
}
assertThrows(IOException.class, new Executable() {
#Override
public void execute() throws Throwable {
htmlService.read("Registration.html", "DrBackmischung");
}
});
}
I've tried mocking it different ways, but nothing seems to work. Is there a working approach?
It seems you are mocking BufferedReader, however the BufferedReader used inside your HTMLService class is new BufferedReader, so it is initializing a new instance of BufferedReader, and definitley not pointing towards your mock instance..
Why dont you just mock the return of the read method() to throw IOException instead.
when(htmlService.read("Registration.html", "DrBackmischung")).thenThrow(IOException.class);
Honesty I cant see the validity of such a test (Towards that a BufferedReader throws an IOException)..unless you have an important business logic (Another method/Service, that could be impacted), but testing an isolated IOException doesnt seem to provide any benefit.

Junit Test for InputStreamReader with Mockito

Can you please help me in writing the Junit test case for the below code?
public class ConsoleReader implements InputReader {
public Cell readInput() {
try {
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
System.out.print("Enter the co-ordinate Seperated by Comma");
String coOrdinates = reader.readLine();
String[] values=coOrdinates.split("\\,");
return new Cell(Integer.parseInt(values[0]),Integer.parseInt(values[1]));
} catch (IOException ioe) {
ioe.printStackTrace();
}
return null;
}
}
Extract the reader as a field. (You can initiaize it either directly or in constructor)
private final BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
Define a getter (either public or protected)
protected BufferedReader getReader(){
return reader;
}
Remove initialization of new BufferedReader(...) from your method. Retrieve it using getReader() instead.
public Cell readInput() {
try {
System.out.print("Enter the co-ordinate Seperated by Comma");
String coOrdinates = getReader().readLine();
String[] values=coOrdinates.split("\\,");
return new Cell(Integer.parseInt(values[0]),Integer.parseInt(values[1]));
} catch (IOException ioe) {
ioe.printStackTrace();
}
return null;
}
In your test class initialize your ConsoleReader as Mockito.spy
ConsoleReader consoleReader = spy(new ConsoleReader());
Mock your getter
private BufferedReader bufferedReader = mock(BufferedReader.class);
#Before
public void setUp() {
doReturn(bufferedReader).when(consoleReader).getReader();
doCallRealMethod().when(consoleReader).readInput();
}
Define your test:
#Test
public void testReadInput() {
when(bufferedReader.readLine()).thenReturn("123,456");
Cell expectedCell = new Cell(123, 456);
Cell actualCell = consoleReader.readInput();
assertEquals(expectedCell, actualCell);
}
You can use Mockito to mock the BufferedReader, like the example below.
BufferedReader bufferedReader = Mockito.mock(BufferedReader.class);
Mockito.when(bufferedReader.readLine()).thenReturn("1", "2", "3");
// You can mock the result based on the type of result you are expecting.

how to acces other class method in java

I have two classes:
class actUI
public class ActUI extends javax.swing.JFrame{
//there are the other classes here
private static void writeToFile(java.util.List list, String path) {
BufferedWriter out = null;
try {
File file = new File(path);
out = new BufferedWriter(new FileWriter(file, true));
for (Object s : list) {
out.write((String) s);
out.newLine();
}
out.close();
} catch (IOException e) {
}
UniqueLineReader ULR = new UniqueLineReader();
ULR.setFileName(path);
}
//there are the other classes here
}
Class UniqueLineReader:
public class UniqueLineReader extends BufferedReader {
Set<String> lines = new HashSet<String>();
private Reader arg0;
public UniqueLineReader(Reader arg0) {
super(arg0);
}
#Override
public String readLine() throws IOException {
String uniqueLine;
while (lines.add(uniqueLine = super.readLine()) == false); //read until encountering a unique line
return uniqueLine;
}
public void setFileName(String filePath){
try {
// Open the file that is the first
// command line parameter
FileInputStream fstream = new FileInputStream("test.txt");
UniqueLineReader br = new UniqueLineReader(new InputStreamReader(fstream));
String strLine;
// Read File Line By Line
PrintWriter outFile2 = new PrintWriter(new File("result.txt"));
String result = "";
List data = new ArrayList();
while ((strLine = br.readLine()) != null) {
// Print the content on the console
System.out.println(strLine);
data.add(strLine);
}
writeToFile(data, "result.txt");
// Close the input stream
//in.close();
} catch (Exception e) {// Catch exception if any
System.err.println("Error: " + e.getMessage());
}
}
}
I want to acces UniqueLineReader from writeToFile method in actUI, but my code is not working, how can i do that with no error?, help me please.
Take a look at your code.
UniqueLineReader ULR = new UniqueLineReader(); // invalid constructor
ULR.setFileName(path);
There is no matching constructor for this. If you want to access writeToFile() from ActUI, Just change access modifier of writeToFile() to public now you can use following
UniqueLineReader.writeToFile(new ArrayList(), path);

Making Java I / O and change the file to split in java

I'm making a project where using java I / O
I have a file with the following data:
170631|0645| |002014 | 0713056699|000000278500
155414|0606| |002014 | 0913042385|000001220000
000002|0000|0000|00000000000|0000000000000000|000000299512
and the output I want is as follows:
170631
0645
002014
file so that the data will be decreased down
and this is my source code:
public class Tes {
public static void main(String[] args) throws IOException{
File file;
BufferedReader br =null;
FileOutputStream fop = null;
try {
String content = "";
String s;
file = new File("E:/split/OUT/Berhasil.RPT");
fop = new FileOutputStream(file);
br = new BufferedReader(new FileReader("E:/split/11072014/01434.RPT"));
if (!file.exists()) {
file.createNewFile();
}
while ((s = br.readLine()) != null ) {
for (String retVal : s.split("\\|")) {
String data = content.concat(retVal);
System.out.println(data.trim());
byte[] buffer = data.getBytes();
fop.write(buffer);
fop.flush();
fop.close();
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
I want is to generate output as above from the data that has been entered
File Input -> Split -> File Output
thanks :)
I think you forgot to mention what problem are you facing. Just by looking at the code it seems like you are closing the fop(FileOutputStream) every time you are looping while writing the split line. The outputStream should be closed once you have written everything, outside the while loop.
import java.io.*;
public class FileReadWrite {
public static void main(String[] args) {
try {
FileReader inputFileReader = new FileReader(new File("E:/split/11072014/01434.RPT"));
FileWriter outputFileWriter = new FileWriter(new File("E:/split/11072014/Berhasil.RPT"));
BufferedReader bufferedReader = new BufferedReader(inputFileReader);
BufferedWriter bufferedWriter = new BufferedWriter(outputFileWriter);
String line;
while ((line = bufferedReader.readLine()) != null) {
for (String splitItem : line.split("|")) {
bufferedWriter.write(splitItem + "\n");
}
}
bufferedWriter.flush();
bufferedWriter.close();
bufferedReader.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}

How to read the first line of a text file in java and print it out?

I want to save a state by write into a file and then read the file later with bufferedReader to get the state again. Here is my code:
public static void main(String[] args) throws IOException{
FileWriter fw = new FileWriter("C:\\Users\\Nicolas\\Desktop\\save.txt");
BufferedWriter save = new BufferedWriter(fw);
save.write("helloWorld");
BufferedReader r = new BufferedReader(new FileReader("C:\\Users\\Nicolas\\Desktop\\save.txt"));
System.out.println(r.readLine());
save.close();
}
If I press run, I got printed out null. I tried it with:
if(r.readLine() != null){
System.out.println(r.readLine());
}
But logically it prints me out nothing now. I don't know what I am doing wrong here. Can you help me please?
When writing to a file with a BufferedWriter, the content is not directly written to disk, as it is obviously buffered. You should flush the content as #ludo_rj suggested in his answer.
Better yet is to close the writer as early as possible, which will automatically flush the content. Closing the reader is also necessary, by the way.
You should go with the following mechanism (I have distributed the approach into several methods to make it more clear):
public class SaveStateTesing {
private static final String FILE_NAME = "C:\\Users\\Nicolas\\Desktop\\save.txt";
public static void main(String[] args) throws IOException {
saveState("helloWorld", FILE_NAME);
String state = readState(FILE_NAME);
System.out.println(state);
}
private static void saveState(String state, String fileName) throws IOException {
try(PrintWriter writer = new PrintWriter(new BufferedWriter(new FileWriter(fileName)))) {
writer.println(state);
}
}
private static String readState(String fileName) throws IOException {
try(BufferedReader reader = new BufferedReader(new FileReader(fileName))) {
return reader.readLine();
}
}
}
Note, that I used the try-with-resource statement, only available in Java 7 (and 8, of course). If you are running it in an older Java version, you must write the methods as following:
private static void saveState(String state, String fileName) throws IOException {
PrintWriter writer = null;
try {
writer = new PrintWriter(new BufferedWriter(new FileWriter(fileName)));
writer.println(state);
} finally {
if (writer != null)
writer.close();
}
}
private static String readState(String fileName) throws IOException {
BufferedReader reader = null;
try {
reader = new BufferedReader(new FileReader(fileName));
return reader.readLine();
} finally {
if (reader != null)
reader.close();
}
}
// Write to file
FileWriter fw = new FileWriter("C:\\Users\\Nicolas\\Desktop\\save.txt");
BufferedWriter save = new BufferedWriter(fw);
save.write("example");
save.flush()
// read as stream
BufferedReader r = new BufferedReader(new FileReader("C:\\Users\\Nicolas\\Desktop\\save.txt"));
System.out.println(r.readLine());
save.close();
A BufferedWriter buffers output until you flush the stream you write to so you need to flush the stream by either closing the file or using save.flush().
public static void main(String[] args) throws IOException {
FileWriter fw = new FileWriter("C:\\Users\\Nicolas\\Desktop\\save.txt");
BufferedWriter save = new BufferedWriter(fw);
save.write("helloWorld");
save.flush(); // this writes the bytes in the stream to the file.
BufferedReader r = new BufferedReader(new FileReader("C:\\Users\\Nicolas\\Desktop\\save.txt"));
System.out.println(r.readLine());
save.close();
}

Categories