1. Overview
1.概述
When unit testing we may occasionally want to test the messages that we write to standard output via System.out.println().
在进行单元测试时,我们可能偶尔想测试一下通过System.out.println()写到标准输出的消息。
Although we’d generally prefer a logging framework over direct interaction with standard output, sometimes this isn’t possible.
尽管我们通常更倾向于日志框架而不是与标准输出直接交互,但有时这是不可能的。
In this quick tutorial, we’ll take a look at a couple of ways we can unit test System.out.println() using JUnit.
在这个快速教程中,我们将看一下我们使用JUnit对System.out.println()进行单元测试的几种方法。
2. A Simple Print Method
2.一种简单的印刷方法
Throughout this tutorial, the focus of our tests will be a simple method that writes to the standard output stream:
在本教程中,我们测试的重点将是一个简单的方法,该方法将写到标准输出流。
private void print(String output) {
System.out.println(output);
}
A quick reminder that the out variable is a public static final PrintStream object which represents the standard output stream intended for system-wide usage.
快速提醒一下,out变量是一个public static final PrintStream对象,它代表标准输出流,旨在供整个系统使用。
3. Working With Core Java
3.使用Core Java工作
Now let’s see how we can write a unit test to check the content of what we send to the println method. However, before we write our actual unit test, we’ll need to provide some initialization in our test:
现在让我们看看如何写一个单元测试来检查我们发送给println方法的内容。然而,在我们编写实际的单元测试之前,我们需要在我们的测试中提供一些初始化。
private final PrintStream standardOut = System.out;
private final ByteArrayOutputStream outputStreamCaptor = new ByteArrayOutputStream();
@BeforeEach
public void setUp() {
System.setOut(new PrintStream(outputStreamCaptor));
}
In the setUp method, we reassign the standard output stream to a new PrintStream with a ByteArrayOutputStream. As we’re going to see this output stream is where the values will now be printed:
在setUp方法中,我们将标准输出流重新分配给一个新的PrintStream,其中有一个ByteArrayOutputStream。正如我们将要看到的,这个输出流就是现在要打印数值的地方。
@Test
void givenSystemOutRedirection_whenInvokePrintln_thenOutputCaptorSuccess() {
print("Hello Baeldung Readers!!");
Assert.assertEquals("Hello Baeldung Readers!!", outputStreamCaptor.toString()
.trim());
}
After we call the print method with the chosen text, we can then verify that the outputStreamCaptor contains the content we were expecting. We call the trim method to remove the new line that System.out.println() adds.
在我们用选定的文本调用print方法后,我们就可以验证outputStreamCaptor是否包含我们所期望的内容。我们调用trim方法来删除System.out.println()添加的新行。
As the standard output stream is a shared static resource used by other parts of the system, we should take care of restoring it to its original state when our test terminates:
由于标准输出流是系统中其他部分使用的共享静态资源,当我们的测试终止时,我们应该注意将其恢复到原始状态:。
@AfterEach
public void tearDown() {
System.setOut(standardOut);
}
This ensures we don’t get any unwanted side effects later on in other tests.
这可以确保我们在以后的其他测试中不会出现任何不必要的副作用。
4. Using System Rules
4.使用系统规则
In this section, we’ll take a look at a neat external library called System Rules which provides a set of JUnit rules for testing code that uses the System class.
在本节中,我们将看看一个整洁的外部库,它叫做系统规则,它提供了一套JUnit规则,用于测试使用系统类的代码。
Let’s start by adding the dependency to our pom.xml:
让我们先把依赖性添加到我们的pom.xml。
<dependency>
<groupId>com.github.stefanbirkner</groupId>
<artifactId>system-rules</artifactId>
<version>1.19.0</version>
<scope>test</scope>
</dependency>
Now, we can go ahead and write a test using the SystemOutRule the library provides:
现在,我们可以继续使用库中提供的SystemOutRule写一个测试。
@Rule
public final SystemOutRule systemOutRule = new SystemOutRule().enableLog();
@Test
public void givenSystemOutRule_whenInvokePrintln_thenLogSuccess() {
print("Hello Baeldung Readers!!");
Assert.assertEquals("Hello Baeldung Readers!!", systemOutRule.getLog()
.trim());
}
Pretty cool! Using the SystemOutRule, we can intercept the writes to System.out. First, we start logging everything written to System.out by calling the enableLog method on our rule. Then we simply call getLog to get the text written to System.out since we called enableLog.
非常酷!使用SystemOutRule,我们可以拦截写到System.out的数据。首先,我们通过调用规则上的enableLog方法,开始记录所有写到System.out的内容。然后,我们简单地调用getLog,以获得我们调用enableLog后写到System.out的文本。
This rule also includes a handy method that returns a log that always has the line separator as \n
这个规则还包括一个方便的方法,该方法返回的日志总是以/n作为行的分隔符。
Assert.assertEquals("Hello Baeldung Readers!!\n", systemOutRule.getLogWithNormalizedLineSeparator());
5. Using System Rules with JUnit5 and Lambdas
5.使用JUnit5和Lambdas的系统规则
In JUnit5, the rules model was replaced by extensions. Luckily, the System Rules library presented in the last section has a variation prepared to work with JUnit5.
在JUnit5中,规则模型被extensions取代。幸运的是,上一节介绍的系统规则库有一个变体,准备与JUnit5一起工作。
System Lambda is available from Maven Central. So we can go ahead and add it to our pom.xml:
系统Lambda可以从Maven中心获得。因此,我们可以继续把它添加到我们的pom.xml中。
<dependency>
<groupId>com.github.stefanbirkner</groupId>
<artifactId>system-lambda</artifactId>
<version>1.0.0</version>
<scope>test</scope>
</dependency>
Now let’s implement our test using this version of the library:
现在让我们用这个版本的库来实现我们的测试。
@Test
void givenTapSystemOut_whenInvokePrintln_thenOutputIsReturnedSuccessfully() throws Exception {
String text = tapSystemOut(() -> {
print("Hello Baeldung Readers!!");
});
Assert.assertEquals("Hello Baeldung Readers!!", text.trim());
}
In this version, we make use of the tapSystemOut method, which executes the statement and lets us capture the content passed to System.out.
在这个版本中,我们利用tapSystemOut方法,该方法执行语句并让我们捕捉传递给System.out的内容。
6. Conclusion
6.结论
In this tutorial, we’ve learned about a couple of approaches for testing System.out.println. In the first approach, we saw how to redirect where we write the standard output stream using core Java.
在本教程中,我们已经了解了测试System.out.println的几种方法。在第一种方法中,我们看到了如何使用核心Java重定向我们编写标准输出流的地方。
Then we saw how to use a promising external library called System Rules using, first, JUnit 4 style rules and then later working with lambdas.
然后,我们看到了如何使用一个很有前途的外部库–系统规则,首先是使用JUnit 4风格的规则,然后是使用lambdas工作。
As always, the full source code of the article is available over on GitHub.
一如既往,文章的完整源代码可在GitHub上获得。