使用JUnit测试函数,其中函数获取用户输入

时间:2016-04-02 14:37:55

标签: java junit inputstream

首先,我试图在这个很酷的网站上寻找一些解决方案。我发现了一个与我的问题有关的问题,但我的测试仍然失败。 我找到的问题可以在这里找到:JUnit testing with simulated user input

让我们看看我的实施:

我有一个用户交互服务类,读取然后验证用户输入:UserInteractionService.java

package Services;

import java.util.Scanner;

public class UserInteractionService {

    private static Scanner scanner = new Scanner(System.in);

    public static int readIntegerAndValidate() {
        while (!scanner.hasNextInt()) {
            System.out.println("It is not a valid integer number. Try again!");
            scanner.next(); 
        }
        return scanner.nextInt();

    }

    public static double readDoubleAndValidate() {
        while (!scanner.hasNextDouble()) {
            System.out.println("It is not a valid number. Try again!");
            scanner.next(); 
        }
        return scanner.nextDouble();
    }
}

当然,我有一个这个服务类的测试类:UserInteractionServiceTest.java

@Test
public void userWriteInput_checkIfItIsInteger_userTypedInteger() {
    String inputData = "5";
    System.setIn(new ByteArrayInputStream(inputData.getBytes()));
    int input = readIntegerAndValidate();
    assertEquals(5, input);
}

@Test
public void userWriteDouble_checkIfItIsDouble_userTypedDouble() {
    String inputData = "5.3";
    System.setIn(new ByteArrayInputStream(inputData.getBytes()));
    double input = readDoubleAndValidate();
    assertEquals(5.3, input, 0);
}

好吧,我的第二个测试函数(userWriteDouble_checkIfItIsDouble_userTypedDouble)失败了,我找不到原因......正如你所看到的,我使用了与de first test相同的模式。你有什么看法,为什么这个测试失败了?我应该使用一些模拟框架(Mockito)吗?提前感谢您的答案!

失败追踪:

java.util.NoSuchElementException
    at java.util.Scanner.throwFor(Unknown Source)
    at java.util.Scanner.next(Unknown Source)
    at Services.UserInteractionService.readDoubleAndValidate(UserInteractionService.java:21)
    at Services.UserInteractionServiceTest.userWriteDouble_checkIfItIsDouble_userTypedDouble(UserInteractionServiceTest.java:23)
...

2 个答案:

答案 0 :(得分:2)

通过使扫描程序保持静态,您更难以测试代码。我会考虑给UserInteractionService一个带有Scanner的构造函数。我建议使用EasyMock,测试中的代码看起来像

import static org.easymock.EasyMock.*;

Scanner scanner = createMock(Scanner.class);
expect(scanner.hasNextDouble()).and return(true).once();
expect(scanner.nextDouble()).and return(5.3).once();

replay(scanner);

您在测试中调用的服务将是

new UserInteractionService (scanner)

答案 1 :(得分:1)

不要为Scanner使用静态字段。它在第一次创建时存储对System.in的引用。在第二次测试中将System.in再次设置为其他值不会更改Scanner的{​​{1}}。像这样修改你的类代码可以修复你的测试。

System.in

顺便说一句,你应该在测试后恢复private Scanner scanner = new Scanner(System.in); 。我编写了一个名为System Rules的库,可以更轻松地为从System.in读取的代码编写测试。