View Javadoc

1   package uk.org.lidalia.test;
2   
3   import java.io.ByteArrayOutputStream;
4   import java.io.OutputStream;
5   import java.io.PrintStream;
6   
7   import org.junit.rules.TestRule;
8   import org.junit.runner.Description;
9   import org.junit.runners.model.Statement;
10  
11  /**
12   * A <a href="https://github.com/junit-team/junit/wiki">JUnit</a> rule that facilitates testing code that prints to
13   * {@link System#out} or {@link System#err}.
14   * <p>
15   * At the start of each test the System.out and System.err PrintStreams are replaced with ones that buffer data passed to them in
16   * memory, allowing the test to retrieve the contents of the buffer at any time and assert on it. At the end of the test the
17   * original PrintStreams are restored allowing access to the console again.
18   */
19  public class SystemOutputRule implements TestRule {
20  
21      private final ByteArrayOutputStream sysOut = new ByteArrayOutputStream();
22      private final ByteArrayOutputStream sysErr = new ByteArrayOutputStream();
23      private final PrintStream originalSysOut = System.out;
24      private final PrintStream originalSysErr = System.err;
25  
26      @Override
27      public Statement apply(final Statement base, final Description description) {
28          return new DebriefableSystemOutputsStatement(base, sysOut, sysErr, originalSysOut, originalSysErr);
29      }
30  
31      /**
32       * @return the data that has been written to System.out since the test began
33       */
34      public String getSystemOut() {
35          return sysOut.toString();
36      }
37  
38      /**
39       * @return the data that has been written to System.err since the test began
40       */
41      public String getSystemErr() {
42          return sysErr.toString();
43      }
44  
45      private static class DebriefableSystemOutputsStatement extends Statement {
46          private final Statement base;
47          private final OutputStream sysOut;
48          private final OutputStream sysErr;
49          private final PrintStream originalSysOut;
50          private final PrintStream originalSysErr;
51  
52          public DebriefableSystemOutputsStatement(final Statement base, final OutputStream sysOut, final OutputStream sysErr,
53                                                   final PrintStream originalSysOut, final PrintStream originalSysErr) {
54              super();
55              this.base = base;
56              this.sysOut = sysOut;
57              this.sysErr = sysErr;
58              this.originalSysOut = originalSysOut;
59              this.originalSysErr = originalSysErr;
60          }
61  
62          @Override
63          public void evaluate() throws Throwable {
64              try {
65                  System.setOut(new PrintStream(sysOut));
66                  System.setErr(new PrintStream(sysErr));
67                  base.evaluate();
68              } finally {
69                  System.setOut(originalSysOut);
70                  System.setErr(originalSysErr);
71              }
72          }
73      }
74  }