【问题标题】:How to listen to (take a copy / split ) System.out messages如何收听(复制/拆分)System.out 消息
【发布时间】:2019-07-17 12:48:07
【问题描述】:

我有一个集成测试 (ClientIT),它使用来自测试助手类 (ClientBasic) 的日志记录输出来确定测试是通过还是失败。我已经重定向了 ClientBasic 类中的 System.out/System.err,以使用 OutputStream 提供返回 ClientIT 的链接,如下所示,

System.setOut(new PrintStream(ClientBasic.out));
System.setErr(new PrintStream(ClientBasic.err));

在哪里,

static OutputStream out;
static OutputStream err;

在 ClientIT 中,我将 Client basic 称为如下,

ClientBasic.process(clientArgs.getArguments(), out, err);

这工作正常,完全符合我的要求,除非我使用 Maven Failsafe 插件作为 Package/Verify 目标的一部分运行它,我收到了消息,

[警告] 通过直接写入本机流损坏 STDOUT forked JVM 1. 查看常见问题网页和转储文件 /path-to-project/target/failsafe-reports/2019-07-17T13-33-44_769-jvmRun1.dumpstream

当 ClientBasic 作为我的集成测试的一部分运行时,它会真正破坏任何日志信息的显示输出 - 从命令行本地运行或在 Jenkins 中运行(使用 mvn ...) - 奇怪的是它仍然可以正常工作当我从 IDE 内部运行它时 - 也许它没有直接调用故障安全插件?

无论如何,上述效果在 Maven 网站上记录为Corrupted STDOUT

所以要尝试解决这个问题,我想做的是简单地连接到 System.out/err 流并创建一个副本 - 即有点像拆分器,而不是重新定向 System.out溪流。

如果可以的话,现在有人吗?如果可以,该怎么做?

【问题讨论】:

  • 所以您使用System.out/err 进行日志记录?使用适当的日志记录怎么样?
  • 您的进程应该直接写入作为参数传递的outerr 流,而不是弄乱系统标准输出。这样,您可以在每次测试之前创建新的独立打印流,确保它们不会被意外更改。在您的代码中应不惜一切代价避免使用System.outSystem.err。无论如何,outerr 参数是该过程的核心部分,还是仅用于记录目的?如果是后者,请摆脱它们并使用 SLF4J 之类的日志框架,并测试进程检查其实际结果而不是日志。
  • @daniu,Luis Inesta 感谢您的建议。代码中已经有相当多的 System.out 了,我可以按照你们的建议用 Logger 替换...但是如果我没记错的话,记录器会将输出发送到文件而不是控制台/std out 或 err ....您有任何示例或链接可以提供帮助吗? PS 在过去,我一直在努力让 Log4j 像记录的那样工作,所以如果有任何更简单的替代方案,我会有点犹豫要不要走这条路。
  • 您可以将日志记录配置为转到文件、控制台或两者。最容易采用的可能是java.util.logging,但也是缺点最多的一个。还是比打印到System.out/err好。
  • 我已尝试使用 SimpleLogger 实现您建议的功能(因为这是系统中正在使用的功能),但我现在不知道如何从记录器中检索值。我为此提出了一个单独的 SO 问题,以防您对此有所了解,stackoverflow.com/questions/57099974/…

标签: java maven maven-failsafe-plugin


【解决方案1】:

由于错误不会立即归咎于setOut/setErr,因此应该可以制作自己的拆分器扩展PrintStream

public class Splitter extends PrintStream {
    public Splitter(PrintStream sysPS, PrintWriter myOut) { ... }
    ... override methods by code generation in IDE.
}

PrintStream myOut = ...;
Splitter outSplitter = new Splitter(System.out, myOut);
Splitter errSplitter = new Splitter(System.err, myOut);
System.setOut(outSplitter);
System.setErr(errSplitter);
...
// At end:
System.setOut(outSplitter.getSysPS());
System.setErr(errSplitter.getSysPS());

IDE 代码生成和一些智能正则表达式替换将为您提供正确的类。


另外可能存在这样的splitter as a Logger

【讨论】:

  • 感谢您的建议。我认为是 System.set 命令(用于 Out 和 Err)导致故障保护插件失败。
  • @robbie70 我会留下我的答案,让人们看看什么是不是解决方案。
猜你喜欢
  • 2017-12-09
  • 1970-01-01
  • 2015-12-10
  • 2018-09-23
  • 2012-04-19
  • 1970-01-01
  • 2015-01-10
  • 1970-01-01
  • 2020-12-26
相关资源
最近更新 更多