JUnit testing with simulated user input
You can replace System.in with you own stream by calling System.setIn(InputStream in).
InputStream can be a byte array:
InputStream sysInBackup = System.in; // backup System.in to restore it later
ByteArrayInputStream in = new ByteArrayInputStream("My string".getBytes());
System.setIn(in);
// do your thing
// optionally, reset System.in to its original
System.setIn(sysInBackup);
Different approach can be make this method more testable by passing IN and OUT as parameters:
public static int testUserInput(InputStream in,PrintStream out) {
Scanner keyboard = new Scanner(in);
out.println("Give a number between 1 and 10");
int input = keyboard.nextInt();
while (input < 1 || input > 10) {
out.println("Wrong number, try again.");
input = keyboard.nextInt();
}
return input;
}
JUnit: How to simulate System.in testing?
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);
}
How to JUnit test a Method with a Scanner?
try this for example:
You could enhance it by simulate the console automatically (see below)
@Test
public void test_scan() throws Exception
{
Myclass myobject=new myobject(); // with args
myobject.load(filename); // you must definie the filename
String result=myobject.scaninput_and_compare(); // you must use scan in, and compare
if (!result.equals(what_I_am_expecting) throw new Exception("EXCEPTION scaninput_and_compare");
// If you arrive here, it's OK
}
If you want to automatize the console input, use that:
Courtesy of: JUnit: How to simulate System.in testing?
String data = "What_I_could_put_in_console";
InputStream stdin = System.in;
System.setIn(new ByteArrayInputStream(data.getBytes()));
Scanner scanner = new Scanner(System.in);
System.setIn(stdin);
Beware of catch Exception inside, to finish with a "good" System.in It's ok for a test alone, for several, you should verify.
With your code:
public String scaninput_and_compare(String filename)
{
Scanner Input = new Scanner(System.in);
String name = Input.nextLine();
BufferedReader br;
try{
br = new BufferedReader(new FileReader(new File(filename)));
String nextLine;
while ((nextLine = br.readLine()) != null)
{
if (nextLine.startsWith("||"))
{
int f1 = nextLine.indexOf("*");
int f2 = nextLine.indexOf("_");
fName = nextLine.substring(f1+1, f2);
if (name.equals(fname))
{
String[] s1 = nextLine.split("_");
String sName = s1[1];
return sName;
}
}
}
// NO GOOD
return "lose";
}
@Test
public void test_scan() throws Exception
{
Myclass myobject=new myobject(); // with args
String filename="good_filename";
// MOCK System.in
String data = "Jack";
InputStream stdin = System.in;
System.setIn(new ByteArrayInputStream(data.getBytes()));
String result=myobject.scaninput_and_compare(filename); // you must use scan in, and compare
// RESTABLISH System.in
Scanner scanner = new Scanner(System.in);
System.setIn(stdin);
if (!result.equals("Davis") throw new Exception("EXCEPTION scaninput_and_compare");
// If you arrive here, it's OK
}
BETTER design, and testing more easy: separate your scanner of System.in, from your file parsing. Just do a function with (filename, fname), and it will be direct to test :
assertEquals(myobject.scaninput_and_compare(filename,"Jack"), "Davis");
Got user input from a for loop in a JUnit test, now how to actually test its output?
The last System.out.println
is still using your replaced PrintStream
, so your output byte array contains two copies. You could store the original System.out
and use that to print to the console.
private final ByteArrayOutputStream output = new ByteArrayOutputStream();
private final PrintStream stdout = System.out;
private final InputStream stdin = System.in;
@Before
public void setUpStreams() {
System.setOut(new PrintStream(output));
}
@After
public void restoreStreams() {
System.setIn(stdin);
System.setOut(stdout);
}
@Test
public void testA() {
example ex = new example();
ByteArrayInputStream in1 = new ByteArrayInputStream("13\n13\n13\n13\n13\n13\n".getBytes());
System.setIn(in1);
ex.methodA();
String out = output.toString();
stdout.println(out);
}
Related Topics
Javafx Freeze on Desktop.Open(File), Desktop.Browse(Uri)
How to View/Change Socket Connection Timeout on Linux
Upload Files from Java Client to a Http Server
Java Embedded Databases Comparison
How to Use Classes from .Jar Files
Exception in Thread "Main" Java.Lang.Noclassdeffounderror: Org/Openqa/Selenium/Webdriver
Linux Command for Extracting War File
How to Debug Java -Jni Using Gdb on Linux
How to Get Rjava 0.9-3 to Work on Os X 10.7.4 with Oracle Java 1.7
Ruby and Duck Typing: Design by Contract Impossible
Why Java Inner Classes Require "Final" Outer Instance Variables
Android: How to Gain Root Access in an Android Application