Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java I/O - Simulate input for System.console()

I am writing a JUnit for a program created in an exercise. That means the test needs to cover as many cases as possible and I don't have any influence on how certain things in the program are implemented. Also, the program runs an infinite loop where at one point, it requires the user to input something.
For the JUnit test I run the program in another Thread and simulate the user input from within the JUnit Thread.

So far, everything works fine if the program reads the user input from System.in, because this stream can easily replaced. But there's also the possiblity that the program interacts with System.console() which currently can not be covered by my test.

Is there any possibility to simulate input for the System.console(), e.g. by replacing its input source with another stream?

(NB: The JUnit test must use Java 6 without any external libraries (except JUnit and Hamcrest).)

Edit: Unfortunately, I can't change the classes of the program to test.

like image 837
darktestuser Avatar asked Feb 11 '23 12:02

darktestuser


2 Answers

After looking at the JDK source code I found the the Console class is reading data from the standard input (System.in):

reader = new LineReader(StreamDecoder.forInputStreamReader(new FileInputStream(FileDescriptor.in), readLock, cs));

Where FileDescriptor.in is a constant pointing to the real standard input (public static final FileDescriptor in = standardStream(0);). So even if you substitute System.in using System.setIn() the console class will still use the real standard input.

Your only option is to substitute the Console object with a mock.

like image 186
Svetlin Zarev Avatar answered Feb 13 '23 04:02

Svetlin Zarev


I think you need to create an abstraction for the console as explained in this post. And use this abstraction in the code instead of System.console(). Then you can mock the abstraction you control in the tests.

EDIT: Another solution which is more involved, is to modify the byte code of System.console() (or sun underlying classes) when it is loaded in the JVM. This is done by providing your own implementation of a ClassLoader and you can find information on how to do that. I'm not sure you want to go this rabbit hole...

like image 45
T.Gounelle Avatar answered Feb 13 '23 03:02

T.Gounelle