The World’s Largest Online Community for Developers

'; java - JUnit test for System.out.println() - LavOzs.Com

I need to write JUnit tests for an old application that's poorly designed and is writing a lot of error messages to standard output. When the getResponse(String request) method behaves correctly it returns a XML response:

public static void setUpClass() throws Exception {
    Properties queries = loadPropertiesFile("");
    Properties responses = loadPropertiesFile("");
    instance = new ResponseGenerator(queries, responses);

public void testGetResponse() {
    String request = "<some>request</some>";
    String expResult = "<some>response</some>";
    String result = instance.getResponse(request);
    assertEquals(expResult, result);

But when it gets malformed XML or does not understand the request it returns null and writes some stuff to standard output.

Is there any way to assert console output in JUnit? To catch cases like:

System.out.println("match found: " + strExpr);
System.out.println("xml not well formed: " + e.getMessage());

using ByteArrayOutputStream and System.setXXX is simple:

private final ByteArrayOutputStream outContent = new ByteArrayOutputStream();
private final ByteArrayOutputStream errContent = new ByteArrayOutputStream();
private final PrintStream originalOut = System.out;
private final PrintStream originalErr = System.err;

public void setUpStreams() {
    System.setOut(new PrintStream(outContent));
    System.setErr(new PrintStream(errContent));

public void restoreStreams() {

sample test cases:

public void out() {
    assertEquals("hello", outContent.toString());

public void err() {
    System.err.print("hello again");
    assertEquals("hello again", errContent.toString());

I used this code to test the command line option (asserting that -version outputs the version string, etc etc)

Edit: Prior versions of this answer called System.setOut(null) after the tests; This is the cause of NullPointerExceptions commenters refer to.

I know this is an old thread, but there is a nice library to do this:

System Rules

Example from the docs:

public void MyTest {
    public final SystemOutRule systemOutRule = new SystemOutRule().enableLog();

    public void overrideProperty() {
        System.out.print("hello world");
        assertEquals("hello world", systemOutRule.getLog());

It will also allow you to trap System.exit(-1) and other things that a command line tool would need to be tested for.

Instead of redirecting System.out, I would refactor the class that uses System.out.println() by passing a PrintStream as a collaborator and then using System.out in production and a Test Spy in the test. That is, use Dependency Injection to eliminate the direct use of the standard output stream.

In Production

ConsoleWriter writer = new ConsoleWriter(System.out));

In the Test

ByteArrayOutputStream outSpy = new ByteArrayOutputStream();
ConsoleWriter writer = new ConsoleWriter(new PrintStream(outSpy));
assertThat(outSpy.toString(), is("expected output"));


This way the class under test becomes testable by a simple refactoring, without having the need for indirect redirection of the standard output or obscure interception with a system rule.

You can set the System.out print stream via setOut() (and for in and err). Can you redirect this to a print stream that records to a string, and then inspect that ? That would appear to be the simplest mechanism.

(I would advocate, at some stage, convert the app to some logging framework - but I suspect you already are aware of this!)

Slightly off topic, but in case some people (like me, when I first found this thread) might be interested in capturing log output via SLF4J, commons-testing's JUnit @Rule might help:

public class FooTest {
    public final ExpectedLogs logs = new ExpectedLogs() {{
        captureFor(Foo.class, LogLevel.WARN);

    public void barShouldLogWarning() {
        assertThat(logs.isEmpty(), is(true)); // Nothing captured yet.

        // Logic using the class you are capturing logs for:
        Foo foo = new Foo();
        assertThat(, is(not(nullValue())));

        // Assert content of the captured logs:
        assertThat(logs.isEmpty(), is(false));
        assertThat(logs.contains("Your warning message here"), is(true));


  • I developed this library since I could not find any suitable solution for my own needs.
  • Only bindings for log4j, log4j2 and logback are available at the moment, but I am happy to add more.

@dfa answer is great, so I took it a step farther to make it possible to test blocks of ouput.

First I created TestHelper with a method captureOutput that accepts the annoymous class CaptureTest. The captureOutput method does the work of setting and tearing down the output streams. When the implementation of CaptureOutput's test method is called, it has access to the output generate for the test block.

Source for TestHelper:

public class TestHelper {

    public static void captureOutput( CaptureTest test ) throws Exception {
        ByteArrayOutputStream outContent = new ByteArrayOutputStream();
        ByteArrayOutputStream errContent = new ByteArrayOutputStream();

        System.setOut(new PrintStream(outContent));
        System.setErr(new PrintStream(errContent));

        test.test( outContent, errContent );

        System.setOut(new PrintStream(new FileOutputStream(FileDescriptor.out)));
        System.setErr(new PrintStream(new FileOutputStream(FileDescriptor.out)));


abstract class CaptureTest {
    public abstract void test( ByteArrayOutputStream outContent, ByteArrayOutputStream errContent ) throws Exception;

Note that TestHelper and CaptureTest are defined in the same file.

Then in your test, you can import the static captureOutput. Here is an example using JUnit:

// imports for junit
import static*;

public class SimpleTest {

    public void testOutput() throws Exception {

        captureOutput( new CaptureTest() {
            public void test(ByteArrayOutputStream outContent, ByteArrayOutputStream errContent) throws Exception {

                // code that writes to System.out

                assertEquals( "the expected output\n", outContent.toString() );

If you were using Spring Boot (you mentioned that you're working with an old application, so you probably aren't but it might be of use to others), then you could use org.springframework.boot.test.rule.OutputCapture in the following manner:

public OutputCapture outputCapture = new OutputCapture();

public void out() {
    assertEquals(outputCapture.toString(), "hello");

Based on @dfa's answer and another answer that shows how to test, I would like to share my solution to give an input to a program and test its output.

As a reference, I use JUnit 4.12.

Let's say we have this program that simply replicates input to output:

import java.util.Scanner;

public class SimpleProgram {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(;

To test it, we can use the following class:

import static org.junit.Assert.*;


import org.junit.*;

public class SimpleProgramTest {
    private final InputStream systemIn =;
    private final PrintStream systemOut = System.out;

    private ByteArrayInputStream testIn;
    private ByteArrayOutputStream testOut;

    public void setUpOutput() {
        testOut = new ByteArrayOutputStream();
        System.setOut(new PrintStream(testOut));

    private void provideInput(String data) {
        testIn = new ByteArrayInputStream(data.getBytes());

    private String getOutput() {
        return testOut.toString();

    public void restoreSystemInputOutput() {

    public void testCase1() {
        final String testString = "Hello!";

        SimpleProgram.main(new String[0]);

        assertEquals(testString, getOutput());

I won't explain much, because I believe the code is readable and I cited my sources.

When JUnit runs testCase1(), it is going to call the helper methods in the order they appear:

  1. setUpOutput(), because of the @Before annotation
  2. provideInput(String data), called from testCase1()
  3. getOutput(), called from testCase1()
  4. restoreSystemInputOutput(), because of the @After annotation

I didn't test System.err because I didn't need it, but it should be easy to implement, similar to testing System.out.

You don't want to redirect the system.out stream because that redirects for the ENTIRE JVM. Anything else running on the JVM can get messed up. There are better ways to test input/output. Look into stubs/mocks.

Full JUnit 5 example to test System.out (replace the when part):

package learning;

import static org.assertj.core.api.BDDAssertions.then;

import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

class SystemOutLT {

    private PrintStream originalSystemOut;
    private ByteArrayOutputStream systemOutContent;

    void redirectSystemOutStream() {

        originalSystemOut = System.out;

        // given
        systemOutContent = new ByteArrayOutputStream();
        System.setOut(new PrintStream(systemOutContent));

    void restoreSystemOutStream() {

    void shouldPrintToSystemOut() {

        // when


You cannot directly print by using system.out.println or using logger api while using JUnit. But if you want to check any values then you simply can use

Assert.assertEquals("value", str);

It will throw below assertion error:

java.lang.AssertionError: expected [21.92] but found [value]

Your value should be 21.92, Now if you will test using this value like below your test case will pass.

 Assert.assertEquals(21.92, str);

for out

void it_prints_out() {

    PrintStream save_out=System.out;final ByteArrayOutputStream out = new ByteArrayOutputStream();System.setOut(new PrintStream(out));

    System.out.println("Hello World!");
    assertEquals("Hello World!\r\n", out.toString());


for err

void it_prints_err() {

    PrintStream save_err=System.err;final ByteArrayOutputStream err= new ByteArrayOutputStream();System.setErr(new PrintStream(err));

    System.err.println("Hello World!");
    assertEquals("Hello World!\r\n", err.toString());

How do I test a private function or a class that has private methods, fields or inner classes?
How do you assert that a certain exception is thrown in JUnit 4 tests?
Conditionally ignoring tests in JUnit 4
JUnit test of the same object
Maven does not find JUnit tests to run
Adding elements to string array String[] and testing the results in Junit
How to jUnit Assert a Grails Controller Update of a Database column?
Trying to use Junit to verify console output matches a string