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
JUnit can be used as a test runner for any kind of test: e.g. system and integration tests; tests which are interacting with a deployed application.
Besides manual testing, JUnit is preferred equally for automation testing. It can also be used along with the Selenium WebDriver to automate tests for web applications. It provides a unique way to write structured, short, and better test cases.
All you have to do is to put JUnit library on the TestNG classpath, so it can find and use JUnit classes, change your test runner from JUnit to TestNG in Ant and then run TestNG in "mixed" mode. This way you can have all your tests in the same project, even in the same package, and start using TestNG.
You can call main method from junit test like this: YourClass. main(new String[] {"arg1", "arg2", "arg3"});
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:
import java.util.Scanner; public class SimpleProgram { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); System.out.print(scanner.next()); scanner.close(); } }
To test it, we can use the following class:
import static org.junit.Assert.*; import java.io.*; import org.junit.*; public class SimpleProgramTest { private final InputStream systemIn = System.in; private final PrintStream systemOut = System.out; private ByteArrayInputStream testIn; private ByteArrayOutputStream testOut; @Before public void setUpOutput() { testOut = new ByteArrayOutputStream(); System.setOut(new PrintStream(testOut)); } private void provideInput(String data) { testIn = new ByteArrayInputStream(data.getBytes()); System.setIn(testIn); } private String getOutput() { return testOut.toString(); } @After public void restoreSystemInputOutput() { System.setIn(systemIn); System.setOut(systemOut); } @Test public void testCase1() { final String testString = "Hello!"; provideInput(testString); SimpleProgram.main(new String[0]); assertEquals(testString, getOutput()); } }
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 from testCase1()
getOutput()
, called from testCase1()
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 testing System.out
.
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
:
String data = "Hello, World!\r\n"; InputStream stdin = System.in; try { System.setIn(new ByteArrayInputStream(data.getBytes())); Scanner scanner = new Scanner(System.in); System.out.println(scanner.nextLine()); } finally { System.setIn(stdin); }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With