Java重定向System.in执行多测试用例时出现空输入流异常如何解决?
问题根因
你Main类中使用的scanner是静态全局实例,它仅会在Main类加载时初始化一次,绑定当时的System.in对象。后续测试中你调用System.setIn更换了输入流,已经初始化完成的Scanner并不会感知到System.in的变更,依然会从已经被读完的旧输入流中读取数据,自然就会抛出输入流为空的NoSuchElementException。
修复方案
方案1:调整业务代码(推荐)
不要复用静态Scanner实例,每次调用in()方法时新建Scanner,绑定当前最新的System.in:
public static int in(String message, int from, int to) { if (message != null && !message.isEmpty()) { System.out.print(message); } // 每次调用都新建Scanner实例 Scanner scanner = new Scanner(System.in); try { String input = scanner.next(); // 原有校验逻辑保持不变 } catch (NoSuchElementException e) { throw new NoSuchElementException("\n\nArguments input incomplete."); } }
如果不想每次调用in()都新建Scanner,也可以在Main类新增重置Scanner的静态方法,测试每次执行前调用:
// Main类新增方法 public static void resetScanner() { scanner = new Scanner(System.in); } // 测试类的set方法末尾补充调用 private static void set(int... args) { // 原有重定向System.in、System.out的逻辑不变 Main.resetScanner(); }
方案2:仅调整测试代码(不修改业务逻辑)
如果不能修改业务代码,可以通过反射在每次测试前重置Main类的静态Scanner字段:
private static void set(int... args) throws Exception { // 原有重定向System.in、System.out的逻辑不变 // 反射重置Scanner Field scannerField = Main.class.getDeclaredField("scanner"); scannerField.setAccessible(true); scannerField.set(null, new Scanner(System.in)); }
额外优化建议
每次测试结束后记得将System.in和System.out恢复为原始默认值,避免影响其他测试用例的执行:
// 测试类新增变量存储原始流 private static final InputStream originalIn = System.in; private static final PrintStream originalOut = System.out; // 每个测试用例执行后恢复流 @AfterEach void restoreSystemIO() { System.setIn(originalIn); System.setOut(originalOut); }
内容的提问来源于stack exchange,提问作者metamorphogenesis
相关产品推荐
相关产品推荐

