【问题标题】:Simulating multiple user input junit模拟多用户输入junit
【发布时间】:2017-04-23 16:28:48
【问题描述】:

我正在尝试编写一个 junit 测试来测试一个需要多个用户输入的方法。 该方法接受一个人对象并为他们设置一个评分,第一个用户输入是评分的双精度值,第二个输入是一个值为“Y”的字符串以确认更改。

我正在尝试使用 ByteArrayInputStream 但它没有获得第二个输入,我在运行测试时遇到的错误是 No line found。

我已经发现了问题,因为我使用不同的方法来验证用户输入我必须每次都创建一个新的扫描仪,所以第二行不被接受

有没有办法为第二个输入再次设置扫描仪?

这是我的测试代码

 Person p = new Person();

    double input1 = 54.3;
    String input2 = "Y";

    String simulatedUserInput = input1 + 
    System.getProperty("line.separator")
    + input2 + System.getProperty("line.separator");


    System.setIn(new ByteArrayInputStream(simulatedUserInput.getBytes(StandardCharsets.UTF_8)));

    addRating(p);

    assertEquals(54.3, p.getMyRating(),0);

添加评分的方法是这样的

    public static void addRating(Person p)
{

    double rating = Validation.validateRating("Please enter a rating for " + p.getName()); // validate input of double

    boolean confirmed = Validation.validateYesNo("Are you sure you wish to set " + p.getName() + "'s rating to " + rating + " Y/N");// confirm yes no

    if (confirmed) 
    {
        p.setMyRating(rating);
    }

}

然后我有一个验证类来确保正确的用户输入, 这是为了评分

    public static double validateRating(String str)
{
    Scanner in = new Scanner(System.in);
    double d = 0;
    boolean valid = false;
    while (!valid)
    {
        System.out.println(str);
        if (!in.hasNextDouble())
        {
            System.out.println("Not a valid number");
            in.nextLine();
        } else
        {

            d = in.nextDouble();

            if(d>=0 && d<=100)
            {
               valid = true; 
            }
            else
            {
                System.out.println("Rating must be between 0 and 100");
            }

        }
    }
    return d;
}

这是用于确认 Y/N 输入

    public static boolean validateYesNo(String str)
{
    Scanner in = new Scanner(System.in);
    boolean YesNo = false;
    boolean valid = false;

    while (!valid)
    {
        System.out.println(str);
        String choice = in.next();
        if (choice.equalsIgnoreCase("Y"))
        {
            valid = true;
            YesNo = true;
        } else if (choice.equalsIgnoreCase("N"))
        {
            valid = true;
            YesNo = false;
        } else
        {
            System.out.println("Invalid input");
        }
    }
    return YesNo;
}

【问题讨论】:

  • System.setIn( 对于单元测试来说,这看起来很丑陋。重构您的代码以将输入字符串作为参数,并从单元测试中调用该方法。在实时代码中,读取字符串并将其作为参数传递很容易,因此无需再实际测试System.in

标签: java junit java.util.scanner


【解决方案1】:

你弄错了单元测试。您不会先编写生产代码;后来发现:这真的很难测试。

相反:从一开始,您就努力编写尽可能简单的代码。理想情况下,您甚至可以在编写生产代码之前编写测试用例。

因为这可以帮助您发现所需的抽象。在您的情况下:为了验证您的 Person 类中的 输入 值,这些值的来源应该并不重要。

换句话说:您确实不是永远不会 ne jamais 将 System.in 读取调用放入您的生产类中。您可能有一个从控制台读取值的测试main 方法;但是您总是将这些值传递到方法中作为参数。如果有的话,您将一个实例 Reader 传递到您的类中。您确实在您的方法中使用 System.in!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-09-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-04-27
    相关资源
    最近更新 更多