I have a Java command-line program. I would like to create JUnit test case to be able to simulate System.in
. Because when my program runs it will get into the while loop and waits for input from users. How do I simulate that in JUnit?
Thanks
I have a Java command-line program. I would like to create JUnit test case to be able to simulate System.in
. Because when my program runs it will get into the while loop and waits for input from users. How do I simulate that in JUnit?
Thanks
You could create a custom
InputStream
and attach it to theSystem
classAnd then use it with your
Scanner
System.in = new FakeInputStream();
Before:
After:
Although I think you should better to test how your class should work with the data read from the input stream and not really how it reads from there.
Try to refactor your code to use dependency injection. Instead of having your a method that uses
System.in
directly, have the method accept anInputStream
as an argument. Then in your junit test, you'll be able to pass a testInputStream
implementation in place ofSystem.in
.maybe like this (not tested):
more parts:
It is technically possible to switch
System.in
, but in general, it would be more robust not to call it directly in your code, but add a layer of indirection so the input source is controlled from one point in your application. Exactly how you do that is an implementation detail - the suggestions of dependency injection are fine, but you don't necessarily need to introduce 3rd party frameworks; you could pass round an I/O context from the calling code, for example.How to switch
System.in
:There are a few ways to approach this. The most complete way is to pass in an InputStream while running the class under test which is a fake InputStream which passes simulated data to your class. You can look at a dependency injection framework (such as Google Guice) if you need to do this a lot in your code, but the simple way is:
Under test you would call the constructor that takes the input stream. You cloud even make that constructor package private and put the test in the same package, so that other code would not generally consider using it.
Based on @McDowell's answer and another answer that shows how to test System.out, I would like to share my solution to give an input to a program and test its output.
As a reference, I use JUnit 4.12.
Let's say we have this program that simply replicates input to output:
To test it, we can use the following class:
I won't explain much, because I believe the code is readable and I cited my sources.
When JUnit runs
testCase1()
, it is going to call the helper methods in the order they appear:setUpOutput()
, because of the@Before
annotationprovideInput(String data)
, called fromtestCase1()
getOutput()
, called fromtestCase1()
restoreSystemInputOutput()
, because of the@After
annotationI didn't test
System.err
because I didn't need it, but it should be easy to implement, similar to testingSystem.out
.