我需要为一个设计很差的旧应用程序编写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());

当前回答

如果您正在使用Spring Boot(您提到您正在使用一个旧的应用程序,所以您可能不是,但它可能对其他人有用),那么您可以以以下方式使用org.springframework.boot.test.rule.OutputCapture:

@Rule
public OutputCapture outputCapture = new OutputCapture();

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

其他回答

您可以设置“系统”。输出输出流通过setOut()(和for in和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());

如果您正在使用Spring Boot(您提到您正在使用一个旧的应用程序,所以您可能不是,但它可能对其他人有用),那么您可以以以下方式使用org.springframework.boot.test.rule.OutputCapture:

@Rule
public OutputCapture outputCapture = new OutputCapture();

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

使用ByteArrayOutputStream和System。setXXX很简单:

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

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

@After
public void restoreStreams() {
    System.setOut(originalOut);
    System.setErr(originalErr);
}

示例测试用例:

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

我使用这段代码来测试命令行选项(断言-version输出版本字符串,等等)

编辑: 这个答案的先前版本在测试后称为System.setOut(null);这就是NullPointerExceptions注释引用的原因。

在使用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);