System Rules:给 java.lang.System 写测试不再抓瞎

System Rules 在 GitHub 上拿了 552 个 Star,数量不算炸裂,但活下来的开源工具里,能持续维护十多年的并不多。这个项目打从早期 JUnit 时代就在用,专门解决一桩很具体的烦人事:测试代码里碰 java.lang.System 的部分。

正文顶部截图

1、它解决什么问题

写 Java 单测时,凡是涉及 System.exitSystem.getPropertySystem.setOutSystem.setErr、标准输入输出的场景,测试就难写。

直接调 System.exit(0),测试进程直接没了。想验证控制台输出,得自己 替换 System.out,写完还要在 finally 里还原回去,否则下一个测试就遭殃。环境变量 System.getenv 更麻烦,Java 早期版本里几乎是只读的。

System Rules 把这层麻烦全包了。它用 JUnit Rules 机制,每个测试结束自动还原现场,并提供断言接口。ExpectedSystemExit 验证退出码,EnvironmentVariables 临时改环境变量,ProvideSystemProperty 覆盖系统属性,断言一气呵成。

2、怎么用

Maven 依赖加上,scope 设成 test:

<dependency>
  <groupId>com.github.stefanbirkner</groupId>
  <artifactId>system-rules</artifactId>
  <version>1.19.0</version>
</dependency>

测试里直接 @Rule 一挂,剩下就是写断言。比如测一个调用 System.exit(2) 的方法:

public class MyTest {
  @Rule
  public final ExpectedSystemExit exit = ExpectedSystemExit.none();

  @Test
  public void exitsWithCode2() {
    exit.expectSystemExitWithStatus(2);
    myClass.doSomething();
  }
}

不用手工管 SecurityManager,不用 try/finally 还原状态。这就是它存在的意义。

README区域截图

3、谁还在用

System Rules 的核心是 JUnit 4 的 Rule 机制。JUnit 5(Jupiter)出来后,这套机制被 Extension 取代了。作者自己也提供了一个替代品 System Lambda,基于 Java 8,和测试框架解耦,能在 JUnit 5 和 TestNG 里用。

所以现状是这样:老项目里 JUnit 4 写的测试,System Rules 仍然是顺手的选择,迁移成本接近零;新项目用 JUnit 5,直接上 System Lambda 更合适。两个项目同一作者,API 风格相通。

4、适合谁

仍在维护 JUnit 4 老代码、测试里频繁碰 java.lang.System 的 Java 工程师,这是刚需。新项目用 JUnit 5 的,看一眼 System Lambda,别走这条老路。

CI 方面,作者在 Travis CI(Linux)和 AppVeyor(Windows)上跑了从 Java 6 到 10 的多版本测试。这点对老项目特别友好,毕竟还在用 Java 6 的项目不在少数。贡献代码时,照着 .editorconfig 写,跑一遍 mvnw test,提 PR 就行。

不在少数。贡献代码时,照着 .editorconfig 写,跑一遍 mvnw test,提 PR 就行。

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐