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

无人久伴 提交于 2019-12-07 07:18:07

问题


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.


回答1:


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.




回答2:


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




回答3:


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){

    }


来源:https://stackoverflow.com/questions/29431697/java-i-o-simulate-input-for-system-console

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!