Java JUnit测试-将void类型方法的stdout输出与字符串进行比较

Java JUnit测试-将void类型方法的stdout输出与字符串进行比较,java,unit-testing,junit,Java,Unit Testing,Junit,我想测试一个将字符串写入标准输出的void类型方法。 对于这个问题,我的团队和我正在尝试将它的输出与我们调用该方法时希望看到的字符串/文本进行比较 注意:我对Java和StackOverflow都是新手,所以如果有更好的方法,我很感激能得到通知 public static boolean test_printAdequateOption(String txt, double[] sol, Formatter out, String expectedOutput) { //O

我想测试一个将字符串写入标准输出的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,这样我可以将其保存为字符串,从而将其与预期的输出参数进行比较。

首先:

  • 命名:只在某个常量中使用u字符;因此,最好调用您的方法
    testPrintAdequateOption()
  • 使测试本身成为JUnit@test;然后;而不是返回布尔值;您在测试代码中创建了一个真正的断言;因此,如果出现意外结果,测试确实会失败(请参见下面的方法)
  • 如果你真的想保持这种方式,这个名字有点误导。您更愿意调用您的方法
    doesprintadequateoptiongivecorrectoredresultson()
    或类似的东西:返回布尔值的方法应该在名称中指明它们是关于布尔值的,这是一个布尔值选择 从纯技术角度来看,上面的代码还可以。除了一个设计问题。。。如果测试写入标准输出的内容是测试代码的“唯一”方法;然后,您应该研究使真正的测试成为可能

    换句话说:你的测试是你能做的最好的;但是你想要测试的东西;事实上你必须这样做。。。这才是真正的问题

    编辑:我不知何故忽略了您真正要求的是JUnit单元测试。因此,让我们给出一个更好的答案,并简单地展示一个真正的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执行;例如,在EclipseIDE中

    请注意:我使用的是assertThat assert,以及is hamcrest matcher。看看那两个


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

    我建议重构代码,使其更易于测试。显然,您的方法printAdequateOption(…)都会格式化/创建字符串,然后调用System.out.println()(或者类似我假设的东西)


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

    这似乎是对您的问题的正确答案:很好。你有什么问题吗?是的,我想了解如何将void类型方法与stringtype方法进行比较。首先,你要了解的是:在编程学校里,我们不会牵着你的手,解决你所有的问题。你从一个问题开始“这个代码行吗”;但是,哎呀,你的代码没有做它应该做的事情;现在请注意,简单的语法错误对您来说似乎是一个真正的大问题。这一切我们都无能为力。尽管如此,我还是会为你们更新一下我的答案。但是真的:不要期望更多。请原谅我的粗鲁,你有没有让你的朋友投票赞成这个问题?我不明白为什么任何独立人士都会这么做。你好,鬼猫,你好,鬼猫,谢谢你的回答。这些测试是为一个大学项目准备的,我们甚至没有被告知使用JUnit。我们在测试用于列出信息的方法时遇到了问题,但正如您在个人观点中所说的,这些方法不可能进行真正的测试。你能告诉我们我们的团队应该做什么吗?为什么要手动构造错误消息?您应该简单地使用断言:
    assert(“输出消息”,baos.toString(),expectedOutput)@user7350907那么这是不是一个JUnit问题?你把这个问题的标题和标签都标上了JUnit。我没有投反对票。我所说的是,如果它旨在成为一个合适的JUnit测试(这是问题本身和您的答案所建议的),那么您不应该手动编写错误消息并将其发送到stdout。您应该使用断言(JUnit、Hamcrest等),以便1。它没有通过测试2。这表明你的意图。它为你构造了合适的信息。对不起,我以前的代码是错误的:P(没有注意到在匆忙)。伟大的回答新手。。。我有点忽略了少年部分;他真的没有充分强调他应该如何重新设计。改变了这一点;你出色的输入得到了+1;-)