Test User input without a mock framework(JUnit)

Park Sehun
2 min readSep 17, 2021

Commonly, when you test the java program especially if there is a user input required (e.g. web application), we use JMeter, LoadRunner, Grinder, Gatling, etc. In rare cases, you may have console input by the user and you need to write unit tests.

I did some tests with JUnit 5 and tried some native testing codes. But remember, even if you want to write Junit testing scripts, you will need to use the mock framework. (e.g. Mockito)

@Test
public void getsIntegerWhenWithinBoundsOfOneToTen() throws Exception {
IntegerAsker asker = mock(IntegerAsker.class);
when(asker.ask(anyString())).thenReturn(3);

assertEquals(getBoundIntegerFromUser(asker), 3);
}

@Test
public void asksForNewIntegerWhenOutsideBoundsOfOneToTen() throws Exception {
IntegerAsker asker = mock(IntegerAsker.class);
when(asker.ask("Give a number between 1 and 10")).thenReturn(99);
when(asker.ask("Wrong number, try again.")).thenReturn(3);

getBoundIntegerFromUser(asker);

verify(asker).ask("Wrong number, try again.");
}

But again, I just wanted to try it without the mock framework.

First of all, you will need InputStream and ByteArrayInput

private final static InputStream systemIn = System.in;
private final static PrintStream systemOut = System.out;
private ByteArrayInputStream typeIn;
private static ByteArrayOutputStream typeOut;

Those will handle Input and Output from the system (User).

@BeforeEach
void setUp() throws Exception {
typeOut = new ByteArrayOutputStream();
System.setOut(new PrintStream(typeOut));
}
@AfterEach
void tearDown() {
System.setIn(systemIn);
System.setOut(systemOut);
}

and in BeforeEach and AfterEach, System.setOut will catch the system out printed and put into the variable (typeOut). The reason we take System.out is that we need to have it to check the correct response from the program is printed.

In actual function,

@Test
final void positiveScenario() {

String simulatedUserInput = "1" + System.getProperty("line.separator") +
"y" + System.getProperty("line.separator") +
"ID001" + System.getProperty("line.separator") +
"100" + System.getProperty("line.separator") +
"c" + System.getProperty("line.separator") +
"300" + System.getProperty("line.separator") +
"2" + System.getProperty("line.separator");

System.setIn(new ByteArrayInputStream(simulatedUserInput.getBytes()));
}

Then whenever the new scanner tries to get input (e.g. scanner.next()) the inputs from the system will give the value one line by line.

There are of course some limitations (drawbacks).

  • The order is important as the program will take input from the first input
  • If the input needs to be used for different purposes, for instance, if the user input needs to be 1,2,3, and sometimes 2,3 only, it will be very difficult to control this.
  • System.in has no reset, clean up, if you need, you still need to take one line by line.
  • It’s not when/ask based, you need to know actual all orders so it can’t manage flexible inputs.

Sign up to discover human stories that deepen your understanding of the world.

Free

Distraction-free reading. No ads.

Organize your knowledge with lists and highlights.

Tell your story. Find your audience.

Membership

Read member-only stories

Support writers you read most

Earn money for your writing

Listen to audio narrations

Read offline with the Medium app

No responses yet

Write a response