07 December 2011
Lots of classes and applications I've written at some point output information to System.out
and System.err
. Sometimes it's quick-and-dirty debugging but if the output is meaningful, testing what's written to either is a pretty simple thing to do.
For this post, I've created a helper class with two static methods that write to System.out
and System.err
:
class SystemOutAndSystemErrHelper {
public static void writeToSystemOut(String text) {
System.out.println("writing '" + text + "' to stdout");
}
public static void writeToSystemErr(String text) {
System.err.println("writing '" + text + "' to stderr");
}
}
Where System.out
and System.err
write output to can be overridden by calling System.setOut
and System.setErr
, supplying PrintStream
instances. The PrintStream
objects themselves are instantiated with an OutputStream
instance that I can easily interrogate later.
In this first test, I instantiate a PrintStream
with a ByteArrayOutputStream
:
@Test
public void dataShouldBeWrittenToSystemOut() {
String newline = System.getProperty("line.separator");
// the PrintStream will be instantiated with a ByteArrayOutputStream
// that we'll read from later
ByteArrayOutputStream baos = new ByteArrayOutputStream();
PrintStream ps = new PrintStream(baos);
System.setOut(ps);
SystemOutAndSystemErrHelper.writeToSystemOut("some output text");
String actual = new String(baos.toByteArray());
String expected = "writing 'some output text' to stdout" + newline;
assertThat(actual, is(expected));
}
After calling System.setOut
with the constructed PrintStream
, the helper object writes some text to System.out
. Testing is as easy then as constructing a String
with the bytes from the ByteArrayOutputStream
and making an assertion about the contents of the output.
Testing the output to System.err
is very similar, the only difference being calling System.setErr
in my test instead:
@Test public void dataShouldBeWrittenToSystemErr() { String newline = System.getProperty("line.separator"); // the PrintStream will be instantiated with a ByteArrayOutputStream // that we'll read from later ByteArrayOutputStream baos = new ByteArrayOutputStream(); PrintStream ps = new PrintStream(baos); System.setErr(ps); SystemOutAndSystemErrHelper.writeToSystemErr("some error text"); String actual = new String(baos.toByteArray()); String expected = "writing 'some error text' to stderr" + newline; assertThat(
actual
, is(expected)); }
If I'm not concerned about which handle the data was written to and only that it got written somewhere, I can pass the same PrintStream
to System.setErr
and System.setOut
:
@Test public void dataShouldBeWrittenToSystemOutAndSystemErr() { String newline = System.getProperty("line.separator"); // the PrintStream will be instantiated with a ByteArrayOutputStream // that we'll read from later ByteArrayOutputStream baos = new ByteArrayOutputStream(); PrintStream ps = new PrintStream(baos); System.setOut(ps); System.setErr(ps); SystemOutAndSystemErrHelper.writeToSystemOut("some output text"); SystemOutAndSystemErrHelper.writeToSystemErr("some error text"); String actual = new String(baos.toByteArray()); String expected = "writing 'some output text' to stdout" + newline + "writing 'some error text' to stderr" + newline; assertThat(
actual
, is(expected)); }
In my examples I used a ByteArrayOutputStream
for simple conversion to a String
, but I could've just as easily used a FileOutputStream
, ObjectOutputStream
, or any other OutputStream
subclass.