I am Currently writing Junit tests for automated testing of student tasks. The topic is console input in java. I have multiple tests that need to take simulated user input and check for correct behaviour of tested methods (method is working fine).
My problem at the moment: the ByteArrayInputStream set as System.in
won't release when needed but one test later (see pic below).
I tried to reset the stream, make it static, make it non-static, have standard System.in
set before and after, tried read method, switched java-versions (from SE13 to 1.8). All attempts at different times, ofc.
Explanation of output in the picture:
It's from our automated JUnit-Framework. Those are two tests reliant on the tested method that takes a user input. The "?" at the start of a line indicate the tested method is active and waiting. First two words after the STARTING TEST line are what is supposed to get injected.
JUnit test code:
final static InputStream STDIN = System.in;
static ByteArrayInputStream bais;
final static String[] INJECTIONS = { "abc", "def", "ghi", "jkl", "mmmm", "klopp", "urgl", "gurle", "ding", "dong" };
private static void inject(String injection, Object o, MethodSignature ms) {
System.out.println(injection);
try {
ByteArrayInputStream bais = new ByteArrayInputStream(injection.getBytes("UTF-8"));
System.setIn(bais);
System.out.println("Injection Bytes: "+injection.getBytes().length);
System.out.println("Available for injection: " + System.in.available());
ms.getMethod().invoke(o);
} catch (Exception e) {
e.printStackTrace();
} finally {
System.setIn(STDIN);
}
}
private static String getStringInject(String injection, Object o, MethodSignature ms) {
String out = null;
System.out.println(injection);
try {
ByteArrayInputStream bais = new ByteArrayInputStream(injection.getBytes("UTF-8"));
System.setIn(bais);
System.out.println("Injection Bytes: "+injection.getBytes().length);
System.out.println("Available for injection: " + System.in.available());
System.in.reset();
out = (String) ms.getMethod().invoke(o);
} catch (Exception e) {
e.printStackTrace();
}
finally {
System.setIn(STDIN);
}
return out;
}
@Test
public void checkReadFromConsoleCorrectReturnTest() {
Object o = createObject(csMain.getC());
if (o == null) {
addFail(csMain.getObjectFail());
return;
}
String injection = INJECTIONS[ThreadLocalRandom.current().nextInt(0, INJECTIONS.length)];
String output = getStringInject(injection + System.lineSeparator() + "END" + System.lineSeparator(), o,
msReadFromConsole);
if (output == null || output.isEmpty()) {
addFail(msReadFromConsole.getMethodNoReturnString());
return;
}
}
@Test
public void checkReadCorrectEndingTriggerTest() {
Object o = createObject(csMain.getC());
if (o == null) {
addFail(csMain.getObjectFail());
return;
}
String injection = INJECTIONS[ThreadLocalRandom.current().nextInt(0, INJECTIONS.length)]
+ System.lineSeparator() + "END" + System.lineSeparator();
inject(injection, o, msRead);
}
Tested java methods:
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.ArrayList;
public class ConsoleReader implements IConsoleReader {
ArrayList<String> reads;
BufferedReader br;
public ConsoleReader() {
reads = new ArrayList<String>();
br = new BufferedReader(new InputStreamReader(System.in));
}
public void read() {
String input = readFromConsole();
while (true) {
if (input == null || input.isEmpty()) {
System.out.println("ERROR: null");
return;
}
input = input.trim().toUpperCase();
if (input.equals("END")) {
System.out.println("Done.");
return;
}
reads.add(input);
input = readFromConsole();
}
}
public String readFromConsole() {
System.out.print("? ");
String out = null;
try {
out = br.readLine();
} catch (Exception e) {
e.printStackTrace();
return null;
}
System.out.println(out);
return out;
}
}
Help is much appreciated. Can't change the Junit library used or add other external libraries atm.