JUnit测试模拟控制台多输入:读取'>1'异常,读取'1'正常
问题分析与解决方案
嘿,我来帮你捋清楚这个问题哈!你遇到的异常完全是因为Scanner.nextInt()的“挑剔”特性——它只认纯整数的输入,当你喂给它>1的时候,开头的>不是有效的数字字符,直接就触发了InputMismatchException,而输入纯1的时候刚好符合它的预期,所以一切正常。
下面给你两种解决思路,看哪种更贴合你的需求:
一、修改原方法,增强鲁棒性(推荐)
原方法没有考虑用户输入非整数的情况,所以遇到带符号或字母的输入直接报错。我们可以改成先读取整行输入,再尝试解析整数,这样就能处理各种无效输入,还能友好提示用户:
public int getMainMenuSelectedOption() { Scanner scan = new Scanner(System.in); int selectedOption = -1; while (true) { try { // 读取整行输入并去除前后空格,避免多余字符干扰 String input = scan.nextLine().trim(); selectedOption = Integer.parseInt(input); // 验证选项是否在合法范围内 if (selectedOption >= 1 && selectedOption <= 5) { break; } else { System.out.println("Invalid option, please select again"); } } catch (NumberFormatException e) { // 捕获非整数输入的异常,提示用户输入有效数字 System.out.println("Please enter a valid integer between 1 and 5"); } } return selectedOption; }
修改后不管用户输入>1、abc还是其他乱七八糟的内容,程序都会给出友好提示,不会直接崩溃。
二、不修改原方法,调整测试输入
如果原方法的需求就是强制用户输入纯整数,那测试时就不能传入>1这种不符合要求的内容。要是你想模拟“用户输入错误后纠正”的场景,可以分两次输入:第一次输入无效内容(比如x),第二次输入合法整数,但要注意原方法此时会抛出异常,所以你需要在测试中捕获这个异常,或者调整测试逻辑。
这里给你一个针对修改后方法的完整测试示例(用你提到的ByteArrayOutputStream来捕获输出):
import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.PrintStream; import static org.junit.jupiter.api.Assertions.assertEquals; public class MenuTest { private final ByteArrayOutputStream outContent = new ByteArrayOutputStream(); private final PrintStream originalOut = System.out; private final ByteArrayInputStream originalIn = (ByteArrayInputStream) System.in; @BeforeEach void setUpStreams() { // 重定向System.out到ByteArrayOutputStream,方便捕获输出 System.setOut(new PrintStream(outContent)); } @AfterEach void restoreStreams() { // 测试结束后恢复原输出和输入流 System.setOut(originalOut); System.setIn(originalIn); } @Test void testGetMainMenuSelectedOption_InvalidThenValid() { // 模拟用户先输入>1,再输入3 String simulatedInput = ">1\n3\n"; System.setIn(new ByteArrayInputStream(simulatedInput.getBytes())); Menu menu = new Menu(); int result = menu.getMainMenuSelectedOption(); // 验证最终返回的选项是否正确 assertEquals(3, result); // 验证是否输出了正确的错误提示 assertEquals("Please enter a valid integer between 1 and 5\n", outContent.toString()); } @Test void testGetMainMenuSelectedOption_ValidInput() { // 模拟用户直接输入合法选项2 String simulatedInput = "2\n"; System.setIn(new ByteArrayInputStream(simulatedInput.getBytes())); Menu menu = new Menu(); int result = menu.getMainMenuSelectedOption(); assertEquals(2, result); // 合法输入时没有错误提示,输出为空 assertEquals("", outContent.toString()); } }
总结一下:如果你的业务场景允许用户输入非整数,那一定要修改原方法让它更健壮;如果原方法就是要求纯整数输入,那测试时就要避免传入不符合格式的内容,或者添加测试用例验证非法输入时的异常情况。
内容的提问来源于stack exchange,提问作者Gavin
相关产品推荐
相关产品推荐

