Linux环境下Java 8无法设文件只读以触发IO异常的问题
解决Linux下单元测试触发IO写入异常的问题
问题根源
Linux的文件权限模型中,文件所有者即使将文件设为r--------权限,依然具备修改文件的能力(内核层面允许所有者绕过自身的读权限限制进行写入,或可先修改权限再写入),这就是你在Linux环境下设置文件只读却无法触发AccessDeniedException的核心原因。
推荐解决方案:Mock模拟IO异常(跨平台、无环境依赖)
单元测试的核心是验证逻辑而非依赖外部环境,用Mock框架模拟IO异常是更优的方案,完全避免操作系统权限差异问题。
场景1:被测方法使用Files.write直接写入
用PowerMock+Mockito Mock静态的Files.write方法,使其抛出指定异常:
@RunWith(PowerMockRunner.class) @PrepareForTest(Files.class) public class FileWriterTest { @Test(expected = IOException.class) public void testIOExceptionHandling() throws Exception { // Mock Files.write静态方法 PowerMockito.mockStatic(Files.class); PowerMockito.when(Files.write(any(Path.class), any(byte[].class), any(OpenOption[].class))) .thenThrow(new IOException("模拟写入权限拒绝")); // 调用被测方法 YourTestedService.writeHelloWorld("/任意路径"); } }
场景2:被测方法使用BufferedWriter写入
MockFiles.newBufferedWriter返回一个模拟的BufferedWriter,并让其write方法抛出异常:
@RunWith(PowerMockRunner.class) @PrepareForTest(Files.class) public class FileWriterTest { @Test(expected = IOException.class) public void testIOExceptionHandling() throws Exception { // 创建模拟的BufferedWriter BufferedWriter mockWriter = Mockito.mock(BufferedWriter.class); Mockito.doThrow(new IOException("模拟写入失败")).when(mockWriter).write(anyString()); // Mock Files.newBufferedWriter静态方法 PowerMockito.mockStatic(Files.class); PowerMockito.when(Files.newBufferedWriter(any(Path.class))).thenReturn(mockWriter); // 调用被测方法 YourTestedService.writeHelloWorld("/任意路径"); } }
可选方案:Linux下真实触发权限异常(仅适合集成测试)
如果一定要依赖真实文件系统,需让测试进程完全失去文件写入权限:
- 创建临时目录并设为
755权限(其他用户可读不可写) - 在该目录下创建文件,将所有者改为非当前测试用户(如
root),并设置文件权限为444 - 用当前测试用户尝试写入该文件,此时会触发
AccessDeniedException
注意:该方案需要测试环境具备切换用户的权限(如sudo),跨平台性差,不推荐作为单元测试方案。
内容的提问来源于stack exchange,提问作者scibuff
相关产品推荐
相关产品推荐

