How can I test multiple inputs from console? - java

I need to test input from console in my program:
Main.java - class with main logic.
public class Main {
public static void main(final String[] args) {
final Integer dividend = new IntegerReader().fetchIntegerNumber("Input dividend: ");
final Integer divisor = new IntegerReader().fetchIntegerNumber("Input divisor: ");
System.out.println(dividend);
System.out.println(divisor);
}
}
IntegerReader.java - reads integer number from input.
import java.util.Scanner;
public class IntegerReader {
public Integer fetchIntegerNumber(final String message) {
System.out.print(message);
final Scanner scanner = new Scanner(System.in);
final String inputString = scanner.nextLine();
scanner.close();
return Integer.valueOf(inputString);
}
}
MainTest.java - test of Main.java class.
class MainTest {
private final InputStream testInputStream = new ByteArrayInputStream("2\n3".getBytes());
private final ByteArrayOutputStream testOutputStream = new ByteArrayOutputStream();
private InputStream initialInputStream = System.in;
private PrintStream initialOutputStream = System.out;
#BeforeEach
void setUpStreams() {
System.setIn(testInputStream);
System.setOut(new PrintStream(testOutputStream));
}
#AfterEach
void restoreDefaultStreams() {
System.setIn(initialInputStream);
System.setOut(initialOutputStream);
System.out.println("Test initial output stream");
}
#Test
void fetchesTextFromInput() {
Main.main(new String[]{});
final String actual = testOutputStream.toString();
assertThat(actual, is("Input dividend: Input divisor: 2\n3"));
}
}
When I run test, I get exception: java.util.NoSuchElementException: No line found.
This exception is thrown, if I try to read second number (divisor) on line:
final String inputString = scanner.nextLine();
How can I fix test, so that exception will not occur?

I would design the IntegerReader in the way that it accepts a scanner:
public class IntegerReader {
private final Scanner scanner;
public IntegerReader(Scanner theScanner) {
this.scanner = theScanner;
}
public Integer fetchIntegerNumber(final String message) {
System.out.print(message);
final String inputString = scanner.nextLine();
return Integer.valueOf(inputString);
}
}
The main class would look like this:
public class Main {
private Scanner scanner;
public Main(Scanner theScanner) {
this.scanner = theScanner;
}
public static void main(final String[] args) {
new Main(new Scanner(System.in)).process();
}
public void process() {
final Integer dividend = new IntegerReader(scanner).fetchIntegerNumber("Input dividend: ");
final Integer divisor = new IntegerReader(scanner).fetchIntegerNumber("Input divisor: ");
System.out.println(dividend);
System.out.println(divisor);
}
}
The test then looks the following way:
// this test still fails, but. ..
public class MainTest {
private final InputStream testInputStream = new ByteArrayInputStream("2\n3\n".getBytes());
private final ByteArrayOutputStream testOutputStream = new ByteArrayOutputStream();
private PrintStream initialOutputStream = System.out;
#Before
public void setUpStreams() {
System.setOut(new PrintStream(testOutputStream));
}
#After
public void restoreDefaultStreams() {
System.setOut(initialOutputStream);
System.out.println("Test initial output stream");
}
#Test
public void fetchesTextFromInput() {
Scanner scanner = new Scanner(testInputStream);
Main main = new Main(scanner);
main.process();
final String actual = testOutputStream.toString();
Assert.assertEquals("Input dividend: Input divisor: 2\n3", actual);
}
}
In this way the scanner is not closed.
Note that the test is not green. I used JUnit, I don't know which technology you used.
Please note:
If I design a class I would not make it dependend on System.*, but give it some stream to work with. This eases testing.
if you use new anywhere in your code you need to know whether the class has the concern to do this or if someone else, a builder or factory should rather create this instance.

You don't want to invoke scanner.close(); because Scanner.close() will close the underlying Closable instance, here System.in and so your dummy test inputstream will be discarded.
Besides even by removing the explicit closing operation it will still fails at runtime :
public Integer fetchIntegerNumber(final String message) {
System.out.print(message);
final Scanner scanner = new Scanner(System.in);
final String inputString = scanner.nextLine();
// REMOVED scanner.close();
return Integer.valueOf(inputString);
}
because the method return will make the scanner eligible to be GC and so System.in will still be closed.
What you want is that System.in.close() be not invoked.
You have two simple ways : Prevent this invocation from the scanner instance or from the underlying resource instance directly (System.in).
You could decorate System.in with FilterInputStream.
For example :
InputStream inWithoutClose = new FilterInputStream(System.in) {
#Override
public void close() throws IOException {
}
}
Then modify the method to test to make it accept this object.

Related

Exception when I insert a different Scanner in different methods

In the main method, I create an object cls and call its method test. This method will call two others methods (test1 and test2). Each one has its Scanner.
public static void main(String[] args) {
Class2 cls = new Class2();
cls.test();
}
the Class2 is:
public class Class2 {
public Class2() {
}
public void test()
{
test2();
test3();
}
public void test2() {
Scanner scanner = new Scanner(System.in);
System.out.println("give a String:");
String str = scanner.next();
scanner.close();
}
public void test3()
{
Scanner sc = new Scanner(System.in);
System.out.println("give another String:");
String str = sc.next();
sc.close();
}
}
After execution, I got an exception
Exception in thread "main" java.util.NoSuchElementException
at java.base/java.util.Scanner.throwFor(Scanner.java:937)
at java.base/java.util.Scanner.next(Scanner.java:1478)
at Class2.test3(Class2.java:25)
at Class2.test(Class2.java:11)
at Class1.main(Class1.java:12)
How can I handle this exception please ? by keeping in each method a different scanner !
Here Is your rectified code with appropriate comments.
Class2.java
import java.util.Scanner;
public class Class2 {
/*You dont have to create multiple scanner objects*/
Scanner scan = new Scanner(System.in);
public void test() {
/*In order to run the methods in this class itself
* you have to use static keyword or create object*/
Class2 obj = new Class2();
obj.test2();
obj.test3();
scan.close();
/* As this method is run, scan.close() should be placed when you want to close InputStream
* you will learn this in Java Streams*/
}
public void test2() {
System.out.println("give a String:");
String str = scan.nextLine();
}
public void test3() {
System.out.println("give another String:");
String str = scan.nextLine();
}
}
Main.java
public class Main {
public static void main(String[] args) {
Class2 cls = new Class2();
cls.test();
}
}
Why did the error occur?
Ans: When your code executes test2() method it closes the scanner InputStream in the ending by using scan.close(), hence when the test3() is executed it can no longer read data. The solution is that you either close scanner in the test3() method or in the test() method.

How to use method showMessage()?

In class we learned about methods, but I'm having a bit of trouble using them.
In a package called util, I wrote a class called IO.
public class IO {
public static float getFloat(){
String str = JOptionPane.showInputDialog("Enter a real number");
return Float.parseFloat(str);
}
public static void showMessage(Scanner s){
System.out.println(s);
JOptionPane.showMessageDialog(null, s);
}
public static Scanner getInput (String prompt){
String s = JOptionPane.showInputDialog(prompt);
return new Scanner(s);
}
}
Also in package util, I have my program, called Program 4.
public class Program4 {
public static void main(String[] args) {
IO.getInput("enter 2 integers");
IO.showMessage(Scanner(s));
}
}
What I don't understand is how do I display the 2 integers entered? One is a scanner object and one is string. How do I use the method getInput to show convert the scanner into a string? Am I going to have to write a new method and use parse?
You can get user input without using Scanner. Here is example:
IO Class
public class IO {
public static float getFloat() {
String str = JOptionPane.showInputDialog("Enter a real number");
return Float.parseFloat(str);
}
public static void showMessage(String s) {
System.out.println(s);
JOptionPane.showMessageDialog(null, s);
}
public static String getInput(String prompt) {
// JOptionPane.showInputDialog() return user input String
String input = JOptionPane.showInputDialog(prompt);
return input;
}
}
Program4 Class
public class Program4 {
public static void main(String[] args) {
// IO.getInput() return stored input String
String input = IO.getInput("enter 2 integers");
IO.showMessage(input);
}
}

How to execute different classes in one class

I want to create a program that can do all the stuff from another code, depending on user input. Something like this:
import java.util.Scanner;
public class Main_Programm1 {
public static void main(String args[]) {
String something = "something";
String something2 = "something2";
Scanner userInput = new Scanner(System.in);
String action = userInput.next();
if (action.equals(something)) {
//here i want to execute all the code from class Main_Programm2
} else if (action.equals(something2)) {
//here i want to execute all the code from class Main_Programm3 and so on
}
}
}
How do i do it?
Actually, you've got it all done, only creates the Objects that you need ;-)
import java.util.Scanner;
// imports classes;
public class Main_Programm1
{
public static void main(String args[])
{
String something = "something";
String something2 = "something2";
Main_Programm main_prog;
Main_Programm2 main_prog2;
Scanner userInput = new Scanner(System.in);
String action = userInput.next();
if (action.equals(something))
{
main_prog = new Main_Programm();
//.....
}
else if (action.equals(something2))
{
main_prog2 = new Main_Programm2();
//.....
}
}
}

Scanner Cannot be Dereferenced

My issue is to create a method called getScanner, and each time it is called, another method can call getScanner to get the next line of input.
Code:
public static void getScanner() {
Scanner input = new Scanner(System.in);
}
public static String getInput() {
String userInput = getScanner().nextLine();
return userInput
}
Error
error: void cannot be dereferenced
String userInput = getScanner().nextLine();
1 error
Essentially, I have multiple methods that need to user Scanner as input, rather than declaring a global or local variable, I want to call one method that will create a Scanner as input each time it is called and assign a variable to this input.
You have set void return type which returns nothing. Since you require a scanner object, return a Scanner in the method.
public static Scanner getScanner() {
Scanner input = new Scanner(System.in);
return input }
public static String getInput() {
String userInput = getScanner().nextLine();
return userInput }
You are not returning an instance of Scanner. Use:
public static Scanner getScanner(){
return new Scanner(System.in);
}
Working Code. Tested and Compiled.
public class testj
{
public static void main(String[] args)
{
System.out.println(getInput());
}
private static String getInput()
{
String userInput = getScanner().nextLine();
return userInput;
}
private static Scanner getScanner()
{
return new Scanner(System.in);
}
}
We have to specify in the method header, what object is getting returned.
Shorter version for getInput()
You can also modify this method as below
private static String getInput()
{
return getScanner().nextLine();
}

Java - Accessing Scanner methods

Hi and hope someone can help. I'm doing a short Java course and need to set up 3 classes that basically communicate between each other but I'm failing.
You'll spot from the code below that I'm trying to split the tasks of reading user's input and doing whatever maths is required into different classes but something's wrong
Any ideas? Thanks for your interest.
Here's the simple Main class:-
public class Main {
public static void main(String[] args) {
Calculator calculator = new Calculator();
calculator.start();
}
}
The Calculator class (or part of it):-
public class Calculator {
private Reader reader;
public void Calculator(Reader reader) {
this.reader = reader;
System.out.println("Calculator set up.");
}
public void start() {
while (true) {
System.out.print("command: ");
String command = reader.readString(); // It fails here:
if (command.equals("end")) {
break;
}
if (command.equals("sum")) {
sum();
} else if (command.equals("difference")) {
difference();
} else if (command.equals("product")) {
product();
}
}
And finally the Reader class:-
public class Reader {
private Scanner input;
public void Reader(Scanner input) {
this.input = input;
System.out.println("Reader set up.");
}
public String readString() {
return input.nextLine();
}
public int readInteger() {
return Integer.parseInt(input.nextLine());
}
}
You have an issue with all the constructors you are using. Constructors are special methods with no return type, so in your case, public void Calculator(Reader reader) needs to be public Calculator(Reader reader) (remove void). The same applies to the other constructors.
Once you do that, you would need to make amendments on how you are instantiating your Calculator class:
Calculator calculator = new Calculator();
Should become:
Calculator calculator = new Calculator(new Reader(new Scanner(System.in)));
provide constructor not mothod.
Calculator(Reader reader) {
this.reader = reader;
System.out.println("Calculator set up.");
}
after that you can change your main method with #subhrajyoti suggested.
apart from above suggestion ,
1> your constructors (Reader and Calculator) is returning void. But constructor cannot return any value. So, remove void keyword.
you have to import Scanner class (i.e. java.util.scanner).

Categories

Resources