You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.26 09:27:58