如何Mock FileWriter构造函数抛出IOException以测试catch块
问题描述
我想Mock FileWriter的构造函数,以此测试代码中的catch块。目标是避免测试时创建文件(测试可能在Windows或类Unix系统运行),同时让FileWriter构造函数抛出IOException。
待测试代码
public void write01() throws IOException { BufferedWriter bufferedWriter = null; try { System.out.println("in try"); FileWriter fw = new FileWriter("c:\\t\\file.txt"); // bufferedWriter = new BufferedWriter(new FileWriter("c:\\t\\file.txt")); bufferedWriter = new BufferedWriter(fw); bufferedWriter.write("dfdf"); } catch (IOException e) { e.printStackTrace(); } finally { bufferedWriter.close(); } }
已尝试的测试方法(未达预期)
public class WriteToFile01Test { // 无效 @Test @Disabled public void testWrite01() throws IOException { try (MockedStatic<FileWriter> fileWriterMock = mockStatic(FileWriter.class)) { fileWriterMock.when(() -> new FileWriter("c:\\t\\file.txt")) .thenThrow(new IOException()); WriteToFile01 writeToFile01 = new WriteToFile01(); writeToFile01.write01(); } } @Test public void testWrite02() throws IOException { try (MockedConstruction<FileWriter> fileWriterMock = mockConstruction(FileWriter.class, (mock, context) -> { when(mock).thenThrow(new IOException()); // doThrow(new IOException()).when(mock); // doThrow(new IOException()).when(mock).write(eq("dfdf")); })) { WriteToFile01 writeToFile01 = new WriteToFile01(); writeToFile01.write01(); } } @Test public void testWrite02a() throws IOException { try (MockedConstruction<FileWriter> fileWriterMock = mockConstruction(FileWriter.class, (mock, context) -> { when(mock).thenThrow(new IOException()); // 抛出NPE:bufferedWriter为null时调用close() // doThrow(new IOException("error happened")).when(mock); // doThrow(new IOException()).when(mock); // doThrow(new IOException()).when(mock).write(eq("dfdf")); })) { WriteToFile01 writeToFile01 = new WriteToFile01(); writeToFile01.write01(); } } // 有效但会创建文件 @Test public void testWrite03() throws IOException { try (MockedConstruction<BufferedWriter> fileWriterMock = mockConstruction(BufferedWriter.class, (mock, context) -> { doThrow(new IOException()).when(mock).write(eq("dfdf")); })) { WriteToFile01 writeToFile01 = new WriteToFile01(); writeToFile01.write01(); } } }
解决方案
1. 先修复待测试代码的NPE隐患
如果FileWriter构造函数抛出异常,bufferedWriter会保持null,此时finally块调用bufferedWriter.close()会触发NullPointerException。优先优化代码:
finally { if (bufferedWriter != null) { bufferedWriter.close(); } }
更推荐用try-with-resources语法彻底避免资源关闭问题:
public void write01() { try (FileWriter fw = new FileWriter("c:\\t\\file.txt"); BufferedWriter bufferedWriter = new BufferedWriter(fw)) { System.out.println("in try"); bufferedWriter.write("dfdf"); } catch (IOException e) { e.printStackTrace(); } }
2. 正确Mock FileWriter构造函数抛出异常
MockedStatic只能mock静态方法,无法拦截构造函数,必须用MockedConstruction来mock对象的构造过程。直接在构造拦截逻辑中抛出异常即可:
@Test public void testWrite01_CatchBlockTriggered() throws IOException { try (MockedConstruction<FileWriter> mockedFileWriter = mockConstruction(FileWriter.class, (mock, context) -> { // 匹配目标路径的构造调用,抛出异常 String filePath = context.arguments().get(0).toString(); if ("c:\\t\\file.txt".equals(filePath)) { throw new IOException("Mocked file access failure"); } })) { WriteToFile01 writeToFile01 = new WriteToFile01(); writeToFile01.write01(); // 可选:验证catch块逻辑,比如结合日志框架捕获异常输出,或修改代码添加可验证的行为 } }
如果不需要精准匹配路径,也可以直接对所有FileWriter构造抛出异常:
@Test public void testWrite01_AllFileWriterThrows() throws IOException { try (MockedConstruction<FileWriter> mockedFileWriter = mockConstruction(FileWriter.class, (mock, context) -> { throw new IOException(); })) { WriteToFile01 writeToFile01 = new WriteToFile01(); writeToFile01.write01(); } }
内容的提问来源于stack exchange,提问作者Oxnard
相关产品推荐
相关产品推荐

