Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/378.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/unit-testing/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何在没有参数的情况下对void方法进行单元测试_Java_Unit Testing_Junit_Switch Statement_Mockito - Fatal编程技术网

Java 如何在没有参数的情况下对void方法进行单元测试

Java 如何在没有参数的情况下对void方法进行单元测试,java,unit-testing,junit,switch-statement,mockito,Java,Unit Testing,Junit,Switch Statement,Mockito,我需要测试一个类,以确定在给定特定输入的情况下是否发生了相关操作。代码是这样的: protected static void receiveInput() { String command; boolean b = true; Scanner scanner = new Scanner(System.in); while (b) { command = scanner.next(); switch(command) {

我需要测试一个类,以确定在给定特定输入的情况下是否发生了相关操作。代码是这样的:

protected static void receiveInput() {
    String command;
    boolean b = true;
    Scanner scanner = new Scanner(System.in);

    while (b) {

        command = scanner.next();
        switch(command) {

            case "first":
                System.out.println("First!");
                break;

            case "second":
                System.out.println("Second!");
                break;

            case "third":
                System.out.println("Third!");
                break;

            default:
                System.out.println("\n***** Invalid *****\n"); 
        }

        System.out.println("\n");
    }

    scanner.close();
}

如果我能以某种方式控制命令字符串并跟踪scanner对象,我可能会得到一个非常彻底的单元测试。出于某种原因,我实际上不允许将这两个对象作为此方法的参数注入。以不同的方式进行此测试有哪些选项?

这是一个使函数更易于测试的完美示例。这个功能不需要输入,也不产生输出,只通过副作用影响世界,通过标准手段使其完全不稳定

要重构此函数以使其更易于测试,请执行以下操作:

  • 不要要求用户通过扫描仪输入,将用户的输入作为输入参数
  • 不要打印结果,返回它
然后,函数的调用方可以决定如何提供输入以及如何处理输出。修改后的程序可以请求用户输入,调用函数,然后打印输出。测试框架可以从要测试的输入列表中提供输入,并根据预期值检查输出。

您可以使用它修改System.in并从文件或ByteArrayInputStream读取


同样,使用重定向输出流。

除了MattPutnam的优秀答案外,还有两个方法的具体提示

1.更改为返回字符串

protected static string receiveInput(String arg) {
    String result;
    String command = arg;
    boolean b = true;

    while (b) {
        switch(command) {

            case "first":
                result = "first";
                break;

            case "second":
                result = "second";
                break;

            case "third":
                result = "third";
                break;

            default:
                result = "\n ****Invalid*** \n"; 
        }
    }
    return result;
}

2.我倾向于测试
布尔b
是否为真。如果是真的,你知道它起作用了,如果不是,它就没有作用Edit:请注意,这可能很危险,因为您不会检查
arg
是否一定符合字符串标准,而是检查它是否有可接受的答案


测试当前方法的唯一方法是以某种方式捕获流,如注释中回答的MattPutnam

您可以使用库测试输出


完全公开:我是系统规则的作者。

您不能将其作为
string
类型的值返回函数,而只返回要检查的特定case字符串?您是否能够更改此方法以使其更易于单元测试?这不是一个非常易于单元测试的方法。通常对我来说,当我对void方法进行单元测试时,这是因为它们会产生某种副作用或状态变化。然后我测试副作用是否正确发生。不幸的是,在这种情况下,不更改方法就很难进行单元测试。您可以将“业务逻辑”封装在一个可测试的方法中,该方法接受输入并返回输出,从而保持
void
方法的完整性。可能更可取的是让该方法接受两个参数,即您提到的标准方法InputStream(或Reader)和OutputStream(或Writer,或PrintWriter)。这是否意味着还有其他方法进行单元测试?这正是我想要的。要按原样进行测试,必须截取输入和输出流。这是可以做到的,但它是丑陋的地狱。伟大的答案!有一本很棒的书,我建议大家,不管有多丰富的经验。。。干净的代码:Robert C.Martin的敏捷软件工艺手册…让我们假设我将尝试测试I/O。我将如何以捕获函数的方式编写它?仅仅证明布尔值是危险的。。。我建议将整个逻辑提取到一个自己的方法中,正如MattPutman所说……这就是为什么我把它列在第1位之后。我明白你为什么说现在我读了我的答案会很危险。我会编辑。@Milesperterson,我强烈建议你接受MattPutnam的回答
public class YourTest {
  @Rule
  public SystemOutRule log = new SystemOutRule().enableLog();
  @Rule
  public TextFromStandardInputStream systemInMock = emptyStandardInputStream();

  @Test
  public void test() {
    systemInMock.provideLines("first", "second");
    ... //execute your code
    assertEquals("First!\nSecond!\n", log.getLogWithNormalizedLineSeparator());
  }
}