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

如何断言OutputStreamWriter包含正确的GZIPOutputStream或FileOutputStream实例

解决方案

你可以通过两种常用方式实现断言,各有优劣可以按需选择:

方法1:反射读取内部私有字段验证(无需修改业务代码)

OutputStreamWriter会把传入的输出流封装到内部的StreamEncoder实例中,我们可以通过两层反射拿到最终的底层流,直接验证类型:

  • 封装反射工具方法:
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.lang.reflect.Field;

public static OutputStream getInnerOutputStream(OutputStreamWriter writer) throws Exception {
    // 第一层:读取OutputStreamWriter持有的StreamEncoder实例
    Field seField = OutputStreamWriter.class.getDeclaredField("se");
    seField.setAccessible(true);
    Object streamEncoder = seField.get(writer);
    
    // 第二层:读取StreamEncoder持有的底层输出流
    Field outField = streamEncoder.getClass().getDeclaredField("out");
    outField.setAccessible(true);
    return (OutputStream) outField.get(streamEncoder);
}
  • 单元测试断言示例:
import org.junit.Test;
import java.io.File;
import java.io.FileOutputStream;
import java.io.FilterOutputStream;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.util.zip.GZIPOutputStream;
import static org.junit.Assert.assertTrue;

@Test
public void testGzFileReturnGzipStream() throws Exception {
    File testGz = File.createTempFile("test", ".gz");
    try {
        OutputStreamWriter writer = (OutputStreamWriter) 你的目标方法(testGz);
        OutputStream innerStream = getInnerOutputStream(writer);
        // 验证是GZIPOutputStream类型
        assertTrue(innerStream instanceof GZIPOutputStream);
        
        // 如需验证GZIP内层是文件输出流,继续反射读取FilterOutputStream的out字段即可
        Field gzipOutField = FilterOutputStream.class.getDeclaredField("out");
        gzipOutField.setAccessible(true);
        OutputStream gzipInner = (OutputStream) gzipOutField.get(innerStream);
        assertTrue(gzipInner instanceof FileOutputStream);
    } finally {
        testGz.delete();
    }
}

@Test
public void testNormalFileReturnFileStream() throws Exception {
    File testTxt = File.createTempFile("test", ".txt");
    try {
        OutputStreamWriter writer = (OutputStreamWriter) 你的目标方法(testTxt);
        OutputStream innerStream = getInnerOutputStream(writer);
        assertTrue(innerStream instanceof FileOutputStream);
    } finally {
        testTxt.delete();
    }
}

注意:该方法依赖JDK内部实现,不同厂商/版本的JDK可能字段名有差异,兼容性稍差

方法2:黑盒验证写入结果(兼容性更强)

不需要依赖JDK内部实现,直接通过实际写入内容的格式验证流类型:

  • 对于.gz后缀文件:往返回的Writer中写入测试字符串,关闭后用GZIPInputStream读取该文件,能正常解压出和写入一致的内容,就说明内层是GZIPOutputStream
  • 对于普通文件:直接读取文件内容和写入内容一致,说明是普通FileOutputStream

这种方法更符合单元测试的黑盒原则,不受JDK版本影响,稳定性更高。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.26 07:06:05