How to Mock System.in and System.out for Java Unit Tests
This guide shows how to replace System.in and System.out with in‑memory streams during unit testing, provides reusable helper classes for setting and restoring these streams, and includes a complete example demonstrating input simulation and output capture in Java.
Mocking System.in and System.out in Java Unit Tests
When a unit test depends on user input via Scanner scanner = new Scanner(System.in), you can replace System.in and System.out with in‑memory streams to simulate input and capture output without manual interaction.
public MockInOut(String input) {
orig = System.out;
irig = System.in;
os = new ByteArrayOutputStream();
try {
System.setOut(new PrintStream(os, false, charset.name()));
} catch (UnsupportedEncodingException ex) {
throw new RuntimeException(ex);
}
is = new ByteArrayInputStream(input.getBytes());
System.setIn(is);
}The constructor saves the original System.out and System.in, redirects System.out to a ByteArrayOutputStream, and feeds the supplied input string to a ByteArrayInputStream. After this setup, calls such as scanner.nextLine() read the prepared input instantly, and any calls to System.out.println write to the buffer instead of the console.
public void close() {
os = null;
is = null;
System.setOut(orig);
System.setIn(irig);
}Calling close() restores the original streams, allowing the test environment to return to its normal state.
import java.io.*;
import java.util.*;
class HelloWorld {
public static void main(String[] args) throws IOException {
PrintStream orig = System.out;
ByteArrayOutputStream os = new ByteArrayOutputStream();
System.setOut(new PrintStream(os, false, "UTF-8"));
// No console output here
for (int i = 0; i < 2; i++) {
System.out.println("FunTester" + i);
}
System.setOut(orig);
// Print the captured output
output("Collected output: " + os.toString("UTF-8"));
InputStream is = System.in;
System.setIn(new ByteArrayInputStream("FunTester
FunTester
".getBytes()));
Scanner scanner = new Scanner(System.in);
// Output all captured input lines
output(scanner.nextLine());
output(scanner.nextLine());
try {
// This will throw because there is no more input
System.out.println(scanner.nextLine());
} catch (NoSuchElementException e) {
e.printStackTrace();
}
System.setIn(is);
scanner = new Scanner(System.in);
// This will wait for user input
System.out.println("Input: " + scanner.nextLine());
}
}This simple approach demonstrates how injecting and swapping streams can isolate I/O dependencies in unit tests, allowing you to focus on the logic under test. More sophisticated mocking frameworks exist, but the presented technique is lightweight and easy to integrate.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
