防止 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
才能成功完成。
我目前正在为 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
才能成功完成。