Junit Testing with Simulated User Input

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



Leave a reply



Submit