【问题标题】:JUnit Testing - Comparing the stdout output of a void type method with a StringJUnit 测试 - 将 void 类型方法的标准输出输出与字符串进行比较
【发布时间】:2023-03-05 08:17:01
【问题描述】:

我想测试一个将字符串写入标准输出的 void 类型方法。 为此,我和我的团队正在尝试将其输出与我们希望在调用该方法时看到的字符串/文本进行比较。

注意:我是 Java 和 StackOverflow 的新手,所以如果有更好的方法可以做到这一点,我会很感激收到通知。

 public static boolean test_printAdequateOption(String txt, double[]
 sol, Formatter out, String expectedOutput) {
         //Obj.
         ByteArrayOutputStream baos = new ByteArrayOutputStream();
         PrintStream ps = new PrintStream(baos);
         PrintStream sout = System.out;

         System.setOut(ps);

         printAdequateOption(txt, sol, out);

         System.out.flush();
         System.setOut(sout);



     return  baos.toString().equals(expectedOutput);
 }

这个测试背后的想法是将方法 printAdequateOption 的输出打印到 PrintStream 中,这样我就可以将其保存为字符串,从而将其与预期的输出参数进行比较。

【问题讨论】:

  • 这似乎是您问题的正确答案:stackoverflow.com/questions/32241057/…
  • 不错。你有问题吗?
  • 是的,我想了解如何将 void 类型的方法与字符串进行比较
  • 首先你要明白:这里不是编程学校,我们牵着你的手和你一起解决所有问题。你从一个问题开始“这个代码可以吗”;但是,哎呀,您的代码没有做它应该做的事情;现在提到简单的语法错误对您来说似乎是一个真正的大问题。我们无能为力所有。尽管如此,我会为你更新我的答案。但实际上:不要期望更多。
  • 对不起,我的粗鲁,你有你的朋友支持这个问题吗?我不明白为什么独立的人会这样做。

标签: java unit-testing junit


【解决方案1】:

我建议重构您的代码以使其更具可测试性。显然,您的方法 printAdequateOption(...) 格式化/创建字符串,然后调用 System.out.println() (或我假设的类似方法)。

您并不真正关心打印到标准输出的 JDK 调用是否适用于正确输入,但您有兴趣检查将打印的字符串是否具有预期的格式。因此,基本上您需要将字符串创建/格式化提取到一个单独的方法中,该方法将返回格式化的字符串。这种方法的测试应该很简单。

【讨论】:

  • 很好的答案新手......我有点忽略了 JUnit 部分;并且真的没有足够强调他应该如何重新设计他的设计。改变了这一点;并且您的出色输入获得了 +1 ;-)
【解决方案2】:

第一:

  1. 命名:您只能在 SOME_CONSTANT 中使用 _ 字符;所以你的方法最好叫testPrintAdequateOption()
  2. 使测试本身成为 JUnit @Test;进而;而不是返回布尔值;你在测试代码中做了一个真正的assert;以便测试真的失败 意外的结果(见下文如何做到这一点)
  3. 如果你真的想保持这种方式,这个名字会有点误导。您宁愿将您的方法称为 doesPrintAdequateOptionGiveCorrectResultsOn() 或类似的名称:返回布尔值的方法应在其名称中表明它们的用途,这是一个布尔值选择!

从纯技术角度来看,上面的代码是可以的。除了一个 design 问题......如果测试写入标准输出的内容是测试代码的“唯一”方法;那么你应该考虑让真正的测试成为可能。

换句话说:你的测试是你能做的最好的;但是你打算测试的东西;分别你必须这样做的事实......这是真正的问题!

编辑:我不知何故忽略了您确实要求进行 JUnit 单元测试。因此,让我们给出一个更好的答案,并简单地展示 real JUnit 测试应该是什么样子:

@Test
public boolean testPrintAdequateOption() {   
     // overwrite stdout to allow for capturing print statement
     ByteArrayOutputStream baos = new ByteArrayOutputStream();
     PrintStream ps = new PrintStream(baos);
     PrintStream sout = System.out;
     System.setOut(ps);

     // call method with specific input
     String text = ...
     double[] sol = ...
     Formatter formatter = ...
     printAdequateOption(text, sol, formatter);

     System.out.flush();
     System.setOut(sout);

     assertThat(baos.toString(), is("expected output));
  }

这就是合理测试的样子;使用 JUnit 执行;例如在您的 Eclipse IDE 中。

请注意:我正在使用 assertThat 断言以及 is hamcrest 匹配器。请参阅here 了解这两个。

有趣的是:当你编写这样一个测试时,很明显你应该简单地改变你的逻辑;正如tomkab 在他的回答中所建议的那样——您不希望printAdequateOption() 生成一个字符串并将其打印到System.out。相反,您需要一种可以直接生成该字符串的方法。所以不要像你在代码中那样绕道!

【讨论】:

  • 你好鬼猫,
  • 您好 GhostCat,感谢您的回复。这些测试是针对大学项目的,我们甚至没有被告知要使用 JUnit。我们在用于列出信息的测试方法中遇到问题,但就像您从个人角度说的那样,这些方法无法进行真正的测试。你能告诉我们我们的团队应该怎么做吗?
  • 为什么要手动构造错误信息?你应该简单地使用断言:assert("output message", baos.toString(), expectedOutput );
  • @user7350907 这是一个 JUnit 问题吗?您在标题和标签中都标记了这个问题 JUnit。
  • 好吧,我没有投反对票。我说的是,如果它旨在成为一个适当的 JUnit 测试(这是由问题本身和您的答案所建议的),您不应该手动编写错误消息并将其发送到标准输出。您应该使用断言(JUnit、Hamcrest 等),以便 1. 它正确地未能通过测试 2. 它显示您的意图 3. 它为您构造正确的消息。对不起,我之前的代码是错误的:P(没有着急注意到)。
猜你喜欢
  • 1970-01-01
  • 2020-04-18
  • 2022-11-22
  • 2019-08-20
  • 2021-08-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多