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.
Related
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.
I have a problem in time while reading from a file because I use in this case scanner.
I have a code fast input but without using a file
so I want to add a file to my code or recommend to me a fast input method using file
public class FastReader {
BufferedReader br;
StringTokenizer st;
public FastReader() {
br = new BufferedReader(new InputStreamReader(System.in));
}
String next() {
while (st == null || !st.hasMoreElements()) {
try {
st = new StringTokenizer(br.readLine());
} catch (IOException e) {
e.printStackTrace();
}
}
return st.nextToken();
}
int nextInt() {
return Integer.parseInt(next());
}
long nextLong() {
return Long.parseLong(next());
}
double nextDouble() {
return Double.parseDouble(next());
}
String nextLine() {
String str = "";
try {
str = br.readLine();
} catch (IOException e) {
e.printStackTrace();
}
return str;
}
}
As was suggested in the comments, you can modify the class to handle file input by adding a parameter to the constructor that allows injecting any InputStream:
public FastReader(InputStream in) {
br = new BufferedReader(new InputStreamReader(in));
}
Then you can use the reader as follows:
FastReader systemInReader = new FastReader(System.in);
FastReader fileReader = new FastReader(new FileInputStream("/path/to/the/file"));
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();
}
I wrtite parser without third-party libraries. Get html code from web site - http://www.cnn.com/ - but some part of code has unicode instead symbols, for example: "\u003cbr/>Sign in to your TV service provider to get access to \u003cbr/>" i think it is problem with encode - how i can fix it? Sorry for my English. Thank you.
public class Main {
public static void main(String[] args) throws IOException {
String commandLine = Scraper.readLineFromConsole();
Reader reader = Scraper.getReader(commandLine);
Scraper.writeInFileFromURL(reader);
}
public static class Scraper {
public static void writeInFileFromURL(Reader out) {
Reader reader = out;
BufferedReader br = new BufferedReader(reader);
try {
PrintWriter writer = new PrintWriter("newFile.txt");
String htmltext;
while (br.ready()) {
htmltext = br.readLine();
writer.write(new String(htmltext));
}
writer.flush();
writer.close();
} catch (IOException e) {
e.printStackTrace();
}
}
public static String readLineFromConsole() {
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
String commandLine = null;
try {
commandLine = reader.readLine();
} catch (IOException e) {
e.printStackTrace();
}
return commandLine;
}
public static Reader getReader(String url)
throws IOException {
// Retrieve from Internet.
if (url.startsWith("http:") || url.startsWith("https:")) {
URLConnection conn = new URL(url).openConnection();
return new InputStreamReader(conn.getInputStream());
}
// Retrieve from file.
else {
return new FileReader(url);
}
}
}
}
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);