views:

2321

answers:

2

Hi. 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:

@BeforeClass
public static void setUpClass() throws Exception {
    Properties queries = loadPropertiesFile("requests.properties");
    Properties responses = loadPropertiesFile("responses.properties");
    instance = new ResponseGenerator(queries, responses);
}

@Test
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 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());
+10  A: 

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!)

Brian Agnew
+1, this is the way: check my example below
dfa
That was something that came to my mind but I couldn't believe there is no standard JUnit way to do that. Thanks, Brain. But the credits got to dfa for the actual effort.
Michał Minicki
+17  A: 

using ByteArrayOutputStream and System.setXXX is simple:

private final ByteArrayOutputStream outContent = new ByteArrayOutputStream();
private final ByteArrayOutputStream errContent = new ByteArrayOutputStream();

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

@After
public void cleanUpStreams() {
    System.setOut(null);
    System.setErr(null);
}

sample test cases:

@Test
public void out() {
    System.out.print("hello");
    assertEquals("hello", outContent.toString());
}

@Test
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)

dfa
That was the sort of thing I contemplated typing in, but never got around to it. +1. Thx
Brian Agnew
Furthemore, I have used JUnitMatchers to test for responses:assertThat(result, containsString("<request:GetEmployeeByKeyResponse"));Thanks, dfa.
Michał Minicki
I prefer to use System.setOut(null) to restore the stream back to what it was when the VM was launched
MrWiggles
The javadocs don't say anything about being able to pass null to System.setOut or System.setErr. Are you sure this will work on all JREs?
finnw
+1 - Google search popped this answer up for me. Thanks, @dfa!
KG