4

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.

2
  • Your class' constructor has to accept a Console object, so you can inject it. Then in the test you will have to construct a mock instance of Console which you'll have to pass to the constructor. Commented Apr 3, 2015 at 14:28
  • @SvetlinZarev see my edit. Is there no other way? Commented Apr 3, 2015 at 15:21

3 Answers 3

5

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.

Sign up to request clarification or add additional context in comments.

Comments

3

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...

1 Comment

Since I cannot influence what the actual program uses as console, the abstraction would be useless because the program would still use System.console() and not my custom console. This would be different, if you could change the console used, like it is possible with System.in using System.setIn()
0

On way i can think of use of mocking scanner class. For example

     int i = sc.nextInt(); 

now mock implementation will be called

 public void Scanner getScanner(){

   }


  // inject mock object for unit testing and in prod ,
      real object with input   stream from console
   public void Scanner setScanner(Scanner scanner){

    }

3 Comments

He is asking about Console not Scanner
but basically he wants to read stream which can be done from scanner too
I don't want to read a stream. I want to simulate input and therefore manipulate the input source of System.console().

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.