我需要为一个设计很差的旧应用程序编写JUnit测试,该应用程序正在向标准输出写入大量错误消息。当getResponse(String request)方法行为正确时,它返回一个XML响应:

@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);
}

但是当它得到格式不正确的XML或不理解请求时,它返回null并将一些东西写入标准输出。

在JUnit中是否有方法断言控制台输出?捕捉以下情况:

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

当前回答

我知道这是一个老线程,但是有一个很好的库可以做到这一点:系统规则 文档中的例子:

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

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

它还允许您捕获System.exit(-1)和命令行工具需要测试的其他内容。

其他回答

您可以设置“系统”。输出输出流通过setOut()(和for in和err)。你能把它重定向到一个打印流,记录到一个字符串,然后检查它吗?这似乎是最简单的机制。

(我主张,在某些阶段,将应用程序转换为一些日志框架-但我怀疑你已经意识到这一点!)

为出

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

    System.setOut(save_out);
}

为犯错

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

    System.setErr(save_err);
}

如果函数打印到系统。输出时,您可以使用系统捕获输出。setOut方法更改系统。输出到由你提供的PrintStream。如果您创建了连接到ByteArrayOutputStream的PrintStream,那么您可以将输出捕获为字符串。

// Create a stream to hold the output
ByteArrayOutputStream baos = new ByteArrayOutputStream();
PrintStream ps = new PrintStream(baos);
// IMPORTANT: Save the old System.out!
PrintStream old = System.out;
// Tell Java to use your special stream
System.setOut(ps);
// Print some output: goes to your special stream
System.out.println("Foofoofoo!");
// Put things back
System.out.flush();
System.setOut(old);
// Show what happened
System.out.println("Here: " + baos.toString());

在使用JUnit时,不能使用system.out.println或logger api直接打印。但如果你想检查任何值,那么你可以简单地使用

Assert.assertEquals("value", str);

它将抛出以下断言错误:

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

您的值应该是21.92,现在如果您将像下面这样使用这个值进行测试,您的测试用例将通过。

 Assert.assertEquals(21.92, str);

有点偏离主题,但如果有些人(比如我,当我第一次发现这个线程时)可能对通过SLF4J捕获日志输出感兴趣,common -testing的JUnit @Rule可能会有所帮助:

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

    @Test
    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(foo.bar(), is(not(nullValue())));

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

免责声明:

我开发了这个库,因为我找不到任何适合我自己需求的解决方案。 目前只有log4j、log4j2和logback的绑定可用,但我很乐意添加更多绑定。