JUnit测试:用户输入

时间:2014-04-28 21:09:06

标签: unit-testing junit user-input

目前正在编写JUnit测试,但在测试依赖用户输入的方法时遇到困难。有没有办法在测试方法中“模拟”用户输入?我有这样的东西(我没有粘贴实际代码,因为方法很长,超出了理解问题的范围;但是,我确实要求用户输入,如果它是错误的,我再次要求它直到输入正确的值):

   public void method(){
    System.out.println("Enter something");
    int a = scanner.nextInt();
    for(;;){
       if(a!=10){
         System.out.println("Please enter another value!");
         a=sc.nextInt();
       else{
         break;
       }
    }
    //further code
   }

2 个答案:

答案 0 :(得分:1)

因为这是互动的,所以很难很好地测试 - 或者至少以可读的方式测试。

测试类似代码的一种常用方法是提取一个接收Scanner和PrintWriter的方法,类似于this StackOverflow answer,并测试:

public void method() {
  method(new Scanner(System.in), System.out);
}

/** For testing. */
public void method(Scanner scanner, PrintWriter output) {
  output.println("Enter something");
  int a = scanner.nextInt();
  // ...
}

这类似于assigning a new stdin/stdout using System.setIn,但更具可预测性,并且需要更少的清理。但是,在这两种情况下,nextInt等方法在等待输入时都会阻塞。除非你想让这个测试多线程(这很复杂),否则你将无法读到你的输出,直到最后,你必须预先指定所有的指令:

@Test
public void methodShouldLaunchTheSpaceShuttle() {
  StringWriter output = new StringWriter();
  String input = "5\n"        // "Please enter another value!"
               + "10\n"       // "Code accepted. Enter command:"
               + "Shuttle\n"; // "Launching space shuttle..."
  systemUnderTest.method(new Scanner(input), new PrintWriter(output));

  assertThat(output.toString(), contains("Please enter another value!"));
  assertTrue(systemUnderTest.spaceShuttleLaunched());
}

也就是说,只要你的说明书很简单(并且没有改变),你可以添加评论(如上所述)并获得一个有价值的测试,将你的代码覆盖率提高到你需要的范围。是

(注意:当然,除了创建一个重载方法,你还可以将" scanner"和#34;输出"作为被测系统中的可变字段。我倾向于比如尽可能保持课堂无国籍,但如果对你或你的同事/导师来说这不是很大的让步。)

答案 1 :(得分:0)

您是否只提供自己的测试值?他们只是int对吗?如果他们是原始值,你就不需要嘲笑任何东西,你可以在给定int s的某一组时测试你的功能:

public void method(){
  int a = // your own test value, or even an array of test values
  for(;;) {
    if (a != 10){
      // check against your test values
    else{
      break;
     }
  }
  //further code
}

如果您依靠外部输入来使您的单元测试工作,那么这些测试并不是真正的单元测试。