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

如何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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.12 13:14:51