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

Java测试中System.setIn输入流异常问题求助

解决System.setIn模拟输入时后续测试抛NoSuchElementException的问题

问题原因

System.in是全局静态资源,第一个测试执行时会将模拟输入流读取至末尾。如果你的UserProfileInteraction内部复用了同一个输入读取对象(比如静态的Scanner实例),后续测试即使重新设置System.setIn,读取对象仍会绑定已耗尽的旧流,导致读取时抛出NoSuchElementException。此外,未在测试前后恢复原始System.in,也可能引发跨测试的资源污染。

解决方案

1. 测试前后恢复原始System.in

用@Before和@After注解,在每个测试执行前保存原始输入流,测试结束后恢复,避免测试间的资源干扰。

2. 确保每次测试都创建新的输入读取实例

检查UserProfileInteraction的实现,确保输入读取对象(如Scanner)是在构造方法中每次重新创建,而非使用静态或复用的实例。

修改后的测试代码示例

public class UserProfileInteractionTest {
    private InputStream originalSystemIn;

    @BeforeClass
    public static void setUpDB() {
        assertTrue(DataBaseOperations.openDBConectionTest());
    }

    @Before
    public void setUpTest() {
        // 保存原始System.in
        originalSystemIn = System.in;
    }

    @Test
    public void registerRegisteredProfileTest(){
        String input = "Test test test\ntest@gmail.com\ntestpassword\n";
        InputStream in = new ByteArrayInputStream(input.getBytes());
        System.setIn(in);
        
        User user = new User();
        UserProfileInteraction register = new UserProfileInteraction(user);
        assertFalse(register.registerAccount());
    }

    @Test
    public void loginRegisteredProfileTest(){
        String input = "test@gmail.com\ntestpassword\n";
        InputStream in = new ByteArrayInputStream(input.getBytes());
        System.setIn(in);
        
        User user = new User();
        UserProfileInteraction register = new UserProfileInteraction(user);
        assertTrue(register.loginAccount());
    }

    @After
    public void tearDownTest() {
        // 恢复原始System.in
        System.setIn(originalSystemIn);
    }

    @AfterClass
    public static void tearDownDB() {
        assertTrue(DataBaseOperations.closeDBConection());
    }
}

关键代码修正(UserProfileInteraction示例)

错误写法(复用静态Scanner):

public class UserProfileInteraction {
    // 静态实例只会初始化一次,后续测试会使用已耗尽的流
    private static Scanner scanner = new Scanner(System.in);

    public UserProfileInteraction(User user) {}

    public boolean registerAccount() {
        String name = scanner.nextLine(); // 后续测试此处会抛异常
        // ...
    }
}

正确写法(每次构造创建新Scanner):

public class UserProfileInteraction {
    private Scanner scanner;

    public UserProfileInteraction(User user) {
        // 每次构造都绑定当前的System.in
        scanner = new Scanner(System.in);
    }

    public boolean registerAccount() {
        String name = scanner.nextLine();
        // ...
        scanner.close(); // 测试场景下关闭流不影响后续操作
    }
}

内容的提问来源于stack exchange,提问作者Jupit90

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.06 04:57:21