-4

我正在尝试在调用使用扫描仪和 System.in 的用户输入的方法上创建一个 junit 测试。

正在测试的方法如下所示:

public void setUserAnswer(){
    Scanner input = new Scanner(System.in);
    userAnswer = input.nextInt();
}

目前,我在 jUnit 中使用以下设置:

StringBuilder sb = new StringBuilder();
        sb.append("");
        sb.append((problem.getOperand1()+problem.getOperand2()));
        String data = sb.toString();
        System.setIn(new ByteArrayInputStream(data.getBytes()));

操作数 1 和操作数 2 是用户添加并输入答案的随机生成的数字。

我遇到的问题是 System.setIn 没有从 jUnit 类传递到正在测试的类。

帮助?

4

2 回答 2

1

为了减少讨论,您的方法可以通过以下方式进行测试:

public class MathProblem {

  private int userAnswer;

  public void setUserAnswer(){
    Scanner input = new Scanner(System.in);
    userAnswer = input.nextInt();
  }

  public int getUserAnswer() {
    return userAnswer;
  }
}

现在测试:

public class MathProblemTest {

  private MathProblem mathProblem;

  @Before
  public void before() throws Exception {
    mathProblem = new MathProblem();
  }

  @Test
  public void testGetUserAnswer() throws Exception {
    StringBuilder sb = new StringBuilder();
    sb.append("41 20");
    String data = sb.toString();
    System.setIn(new ByteArrayInputStream(data.getBytes()));

    mathProblem.setUserAnswer();

    assertThat(mathProblem.getUserAnswer(), equalTo(41));
  }

}

正如其他人已经提到的那样:此代码的行为符合预期。

因此,如果您没有看到正确的行为,则测试可能会被破坏,或者问题出在您尚未发布的代码的另一个区域。所以问问你自己:你的例子与这个例子有什么不同?

于 2015-10-04T12:36:20.023 回答
0

不应该在单元测试System.in期间搞乱。

问问自己你正在测试什么。您是在测试Scanner代码,还是使用用户输入的任何值的代码?

您的代码可能会做 3 件事:

  • 询问用户输入
  • 执行操作
  • 显示结果

单元测试中,您正在测试操作,而不是用户提示或显示逻辑。或者如果你这样做,它们应该是 3 个不同的单元测试,并且记住,如果你正在测试用户提示,你正在测试 的使用,而Scanner不是 Scanner 是否可以读取System.in

因此,首先将您的代码拆分为:

public class MyClass {
    public static void main(String[] args) {
        Input input = promptUserForInput(new Scanner(System.in), System.out);
        Result result = performOperation(input);
        printResult(System.out, result);
    }
    // methods here
}

如果它们是简单值Input,则不必创建新类。Result它们也可以是同一个类,例如MyClass.

这样您就可以测试该操作是否适用于各种输入,这是您最关心的问题。

@Test
public void testOperation1() {
    Input input = new Input(5, 15, true); // true means subtract
    Result result = MyClass.performOperation(input);
    assertEquals(-10, result.getValue());
}

@Test
public void testOperation2() {
    Input input = new Input(5, 15, false); // false means add
    Result result = MyClass.performOperation(input);
    assertEquals(20, result.getValue());
}

如果需要,您还可以测试用户提示和结果打印。

@Test
public void testPrompt() {
    String userInput = "5 15\nYes";
    PrintStream out = new PrintStream(new ByteArrayOutputStream());
    Input input = MyClass.promptUserForInput(new Scanner(userInput), out);
    assertEquals(5, input.getNum1());
    assertEquals(15, input.getNum2());
    assertTrue(input.isSubtractRequested());
}

@Test
public void testPrint() {
    ByteArrayOutputStream buf = new ByteArrayOutputStream();
    try (PrintStream out = new PrintStream(buf)) {
        MyClass.printResult(out, new Result(-10));
    }
    String outText = new String(buf.toByteArray());
    assertEquals("Result is -10\r\n", outText);
}
于 2015-10-04T13:08:16.677 回答