I have built an interactive java app using Scanner class. I want to test it with Junit 5.
After searching a but I wrote the test case for simulating the shell. The test case runs for the first command and remains stuck in the main method. It doesn't return the console out. My subsequent commmands are not executed due to it.
public static void main(String[] args) {
final Scanner scanner = new Scanner(System.in);
while (true) {
final String input = scanner.nextLine();
if (input.equalsIgnoreCase("exit")) {
printMsg("Exiting the application..");
System.exit(1);
}
else {
printMsg("User Input >>>> " + input);
final CommandProcessor commandProcessor = new CommandProcessor();
try {
commandProcessor.process(input);
}
catch (Exception e) {
System.out.println("An error occurred - " e.getLocalizedMessage() + ". Please try again.");
}
}
}
}
public class CommandProcessor {
public void process(final String input) throws Exception {
//Some validations
final CommandHandler commandHandler = CommandHandlerFactory.getHandler(inputCommand);
commandHandler.execute(args);
}
}
}
public class CreateCommandHandler extends CommandHandler {
@Override
void handle(final String[] args) throws Exception {
final int units = Integer.parseInt(args[1]);
System.out.println("Created units " + units);
}
}
class ApplicationTest {
private static final InputStream systemIn = System.in;
private static final PrintStream systemOut = System.out;
private static InputStream testIn;
private static OutputStream testOut;
@BeforeEach
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();
}
@AfterEach
public void resetSystemInputOutput() {
System.setIn(systemIn);
System.setOut(systemOut);
}
@Test
public void testCreateSuccess() {
String testString = "create 2";
provideInput(testString);
Application.main(new String[0]);
assertEquals("Created units - 2", getOutput());
//Verifying the empty state. Another handler is invoked for it.
provideInput("status");
assertEquals("No units assigned", getOutput());
//exiting the shell.
provideInput("exit");
}
// @Test
public void testStatusAfterCreateParkingLotSuccess() {
String testString = "status";
provideInput(testString);
Application.main(new String[0]);
assertEquals(AppConstants.PARKING_LOT_IS_EMPTY, getOutput());
resetSystemInputOutput();
provideInput("exit");
Application.main(new String[0]);
}
@AfterAll
public static void exit() {
//System.setIn(new ByteArrayInputStream("exit".getBytes()));
}
}
The unit test, testCreateSuccess(), runs only the create command and then it keeps waiting for the next input. The control is not returning back to the test to send the next command. Why is it behaving different here? When I run the shell I can enter commands 1 by 1. How can I achieve the same behaviour in the test cases? There any 5-6 commands which I need to run and verify using Junit. Any help is appreciated. I also want to process these commands from a txt file.