Reputation: 21161
I have a JUnit test class, which uses Mockito, in which I need to test if something is being logged correctly. It basically looks something like:
public class MyTest {
private final PrintStream outDefault = System.out;
private final PrintStream errDefault = System.err;
private final ByteArrayOutputStream outContent = new ByteArrayOutputStream();
private final ByteArrayOutputStream errContent = new ByteArrayOutputStream();
@Before
public void setUp() {
System.setOut(new PrintStream(outContent));
System.setErr(new PrintStream(errContent));
}
@After
public void tearDown() {
System.setOut(outDefault);
System.setErr(errDefault);
}
@Test
public void Test1_Condition_Expected() {
assertTrue(errContent.toString().toLowerCase().contains("..."));
}
...
@Test
public void TestN_Condition_Expected() {
assertTrue(errContent.toString().toLowerCase().contains("..."));
}
}
I have also tried to do a flush and close of the streams in the @After, but it does not seem to work neither:
@After
public void tearDown() {
try {
outContent.flush();
errContent.flush();
outContent.close();
errContent.close();
} catch (IOException e) {
e.printStackTrace();
}
System.setOut(outDefault);
System.setErr(errDefault);
}
When I run the whole class, the first tests passes but the rest don't. If I run the tests one by one then all of them pass.
I have debugged the code and everything seems to work properly, but for tests other than the first one the streams are not getting the logs, so obviously they fail.
Upvotes: 0
Views: 234
Reputation: 24520
The PrintStream is not flushed when you call errorContent.toString()
because @After
is called after your test and it flushes only errorContent
. You have to flush the PrintStream around errorContent
before calling toString()
. The best way is to use PrintStream
with autoFlush
enabled.
@Before
public void setUp() {
System.setOut(new PrintStream(outContent, true));
System.setErr(new PrintStream(errContent, true));
}
Upvotes: 1
Reputation: 95654
Note that the ByteArrayOutputStreams you're flushing:
outContent.flush();
errContent.flush();
...aren't the PrintStreams you're setting:
System.setOut(new PrintStream(outContent));
System.setErr(new PrintStream(errContent));
...and that PrintStream owns a BufferedWriter and can be set to auto-flush, but doesn't do so by default:
Optionally, a
PrintStream
can be created so as to flush automatically; this means that theflush
method is automatically invoked after a byte array is written, one of theprintln
methods is invoked, or a newline character or byte ('\n'
) is written.
My guess is that it's the PrintStream that needs to be flushed before each assertion against toString()
, not the ByteArrayOutputStream.
Upvotes: 1