为什么在Java JUnit 4.13中无法测试FileNotFoundException异常
问题根因
你的JUnit测试无法触发预期异常的核心原因是:构造方法内部已经捕获了FileNotFoundException,且仅打印堆栈跟踪,没有将异常向外抛出。
JUnit的@Test(expected = XXXException.class)注解只会检测测试目标方法未捕获、向外抛出的异常。你在构造方法内把异常吞掉后,构造方法会正常执行完成并返回实例,JUnit自然无法检测到预期异常,测试就会失败。
解决方案
根据你的业务需求可以二选一:
方案1:构造方法抛出异常(推荐,符合错误处理的开闭原则)
如果业务逻辑要求传入非法文件名时必须抛出异常由上层调用方处理,直接修改构造方法的异常处理逻辑,要么直接声明抛出受检异常,要么捕获后重新抛出:
// 方式1:直接声明抛出受检异常,去掉内部不必要的catch块 public LanguageManager(String file) throws IOException { this.languages = new ArrayList<Language>(); BufferedReader in = new BufferedReader(new InputStreamReader(new FileInputStream(file), "utf-8")); String line; while((line = in.readLine()) != null) { line = line.trim(); if (line.equals("") || line.startsWith("#")) continue; Language j = new Language(line); this.languages.add(j); } in.close(); } // 方式2:保留日志打印,捕获后重新抛出异常 public LanguageManager(String file) throws FileNotFoundException { this.languages = new ArrayList<Language>(); try { BufferedReader in = new BufferedReader(new InputStreamReader(new FileInputStream(file), "utf-8")); String line; while((line = in.readLine()) != null) { line = line.trim(); if (line.equals("") || line.startsWith("#")) continue; Language j = new Language(line); this.languages.add(j); } in.close(); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } catch (FileNotFoundException e) { e.printStackTrace(); throw e; // 重新抛出异常,让JUnit可以检测到 } catch (IOException e) { e.printStackTrace(); } }
同时修改测试方法,声明抛出对应的受检异常:
@Test(expected=FileNotFoundException.class) public void testLanguageManager() throws Exception { new LanguageManager("non_existing_file.txt"); }
方案2:调整测试逻辑(适合需要构造方法容错的场景)
如果业务要求构造方法即使传入非法文件也不能抛出异常,那你需要调整测试逻辑,不再校验异常抛出,改为校验构造后的对象状态:比如languages集合是否为空、是否完成了初始化等。
内容的提问来源于stack exchange,提问作者Milos Stojanovic
相关产品推荐
相关产品推荐

