背景
在进行单元测试时,被测试的业务代码没有明确的return类型,但是一般的执行记录都会写入logger中,并在控制台输出。普通的断言无法覆盖这种场景,修改代码只能短时解决问题,每次更新都需要再次改代码。因此需要一种方法能够检测控制台的输出,并对输出进行断言。
解决方案一
- 把标准输出定向至ByteArrayOutputStream中去
- 对其内容进行断言
- 因为其内容较多,使用
assertThat
方法的containsString进行部分匹配。
注:
- 使用断言必须引用import static org.junit.Assert.*;
- 使用containsString
必须引用import static org.hamcrest.Matchers.containsString;
import org.junit.Test;
import org.junit.runner.RunWith;
import static org.junit.Assert.*;
import static org.hamcrest.Matchers.containsString;
public class SomeCodeTest {
private SomeCode somecode;
@Test
public void testOneParagraph () {
//把标准输出定向至ByteArrayOutputStream中
final ByteArrayOutputStream outContent = new ByteArrayOutputStream();
System.setOut(new PrintStream(outContent));
//执行要测试的程序
somecode.exec();
//对控制台的输出进行部分匹配断言
assertThat(outContent.toString(), containsString("Hello"));
}
}
解决方案二
- 使用System Rules,这种方法更加灵活。
- **注:**JUnit本身的包里没有SystemOutRule,需要把jar包加入到buildpath中。
Maven
<dependency>
<groupId>com.github.stefanbirkner</groupId>
<artifactId>system-rules</artifactId>
<version>1.16.0</version>
<scope>test</scope>
</dependency>
Gradle、Grails
testCompile 'com.github.stefanbirkner:system-rules:1.16.0'
Ivy
<dependency org="com.github.stefanbirkner" name="system-rules" rev="1.16.0" conf="test">
<artifact name="system-rules" type="jar"/>
</dependency>
Groovy Grape
@Grapes(
@Grab(group='com.github.stefanbirkner', module='system-rules', version='1.16.0')
)
2、实际代码如下:
import org.junit.Test;
import org.junit.runner.RunWith;
import static org.junit.Assert.*;
import static org.hamcrest.Matchers.containsString;
public class SomeCodeTest {
private SomeCode somecode;
@Rule
public final SystemOutRule log = new SystemOutRule().enableLog();
@Test
public void testOneParagraph () {
log.clearLog();
//执行要测试的程序
somecode.exec();
//对控制台的输出进行部分匹配断言
assertThat(log.getLog(), containsString("Hello"));
}
}