防止 JUnit 测试陷入 while 循环

Prevent JUnit test from getting stuck in while-loop

我目前正在为 Replit.com 教育团队的一些作业编写一些 JUnit 测试。我有一个测试卡住了,我相信,因为 main 方法中的 while 循环。如果第一个输入有效,根据程序,测试运行。如果第一个输入无效,测试就会卡住。

这是测试:

@Test
public void validPW(){
String correctOutput = "Enter a password >>  Not enough uppercase letters!\nNot enough digits!\nReEnter a password >> Valid password\nGoodbye!";
  try{
    // IMPORTANT: Save the old System.out!
    PrintStream old = System.out;

    // Create a stream to hold the output
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    //PrintStream ps = new PrintStream(baos);
    System.setOut(new PrintStream(baos, false, "UTF-8"));

    // IMPORTANT: save old Sytem.in!
    InputStream is = System.in;

    // Set new System.in
    System.setIn(new ByteArrayInputStream("Iljvm4\nVaGN76js\n".getBytes()));

    // Calling main method should save main method's output as string literal to baos.
    String[] requiredArray = {"Hello", "There"};
    ValidatePassword.main(requiredArray);

    // Put things back
    System.out.flush();
    System.setOut(old);

    //Restore
    System.setIn(is);


    assertEquals(correctOutput, baos.toString());
  }catch(IOException ioe){
     new IOException("i/o problem - test not executed\n");
   }
}

程序如下:

import java.util.*;

public class ValidatePassword {
    public static void main(String[] args) {

        String passWord;
        boolean Valid = false;

        final int NUM = 2; // two digits and two Upper case letters
        // counters to count the required digits and letters
        int upperCount = 0;
        int lowerCount = 0;
        int digitCount = 0;

        while (!Valid) {
            
            Scanner in = new Scanner(System.in);
            int numSpaces = 0;
            System.out.print("Enter a password >> ");
            passWord = in.next();
            in.nextLine(); // capture dangling newline char.
            // Using a for loop to iterate over each character in the String
            for (int i = 0; i < passWord.length(); i++) {
                char ch = passWord.charAt(i);
                if (Character.isUpperCase(ch)){ // Using the Character class's methods
                    upperCount++;
                }
                else if (Character.isLowerCase(ch)){
                    lowerCount++;
                }
                else if (Character.isDigit(ch)){
                    digitCount++;
                }
            }

            if (upperCount >= NUM && lowerCount >= 3 && digitCount >= NUM) {
                System.out.println("Valid password\nGoodbye!");
                Valid = true;   
            } else {                
                if (upperCount < NUM)
                    System.out.println("Not enough uppercase letters!");
                if (lowerCount < 3)
                    System.out.println("Not enough lowercase letters!");
                if (digitCount < NUM)
                    System.out.println("Not enough digits!");
                System.out.print("Re");
                // Resetting the counters if not a valid password
                upperCount = 0;
                lowerCount = 0;
                digitCount = 0;

            }            
        }
    }
}

首先,ValidatePassword 中的代码尝试读取输入流的末尾,因此需要将扫描器初始化移出循环,并且需要检查条件 in.hasNextLine()

此外,最好使用 passWord = in.nextLine(); 行的单个读数而不是一对 in.next(); in.nextLine();.

这两个修复应该可以解决循环不正确的问题。

        Scanner in = new Scanner(System.in);
        while (!Valid && in.hasNextLine()) {
            
            int numSpaces = 0;
            System.out.print("Enter a password >> ");
            passWord = in.nextLine();
            //in.nextLine(); // capture dangling newline char.
        // ... keep the rest as is

最后一个 correctOutput 需要修复 assertEquals 才能成功完成。