Junit test of method with Scanner and System.in (Java)

2.3k views Asked by At

I'm new to programmming and I have this simple method:

public double input() {
        double result = 0;
        Scanner scanner = new Scanner(System.in);
        if (scanner.hasNextDouble()) {
            result = scanner.nextDouble();
        } else {
            System.out.print("Please, type numbers!\n");
        }
        return result;
    }

The question is how to simulate (emulate) user's input from the keyboard in junit test.

2

There are 2 answers

0
janos On BEST ANSWER

Pass a Scanner as input parameter to the method you want to test. In your test code, you can create a Scanner instance from a string:

Scanner scanner = new Scanner("the sample user input");

And then in the production code, you can pass new Scanner(System.in) to the method.

0
Mritunjay On

You should read more about dependency injection.

Your Class shouldn't be tightly coupled with other classes. Dependencies can be provided to objects at multiple levels according to the need.

  1. Using constructor/setter if it is a field.
  2. Using method parameters if the scope is just in a method.

In your case as soon as you say:-

Scanner scanner = new Scanner(System.in);

Now your code is fully coupled with System.in stream. Instead you should inject this as a parameter to your method in below format.

public double input(InputStream inputStream) {
    double result = 0;
    Scanner scanner = new Scanner(inputStream);
    if (scanner.hasNextDouble()) {
        result = scanner.nextDouble();
    } else {
        System.out.print("Please, type numbers!\n");
    }
    return result;
}

Now from your main code you can call it with System.in. From your test class you call it with any InputStream. Mostly we use a mock/stub for it.

Note:- Above it just an example, and can be change according to need.