当文件存在且无法删除时,如何测试方法异常?

How test an method exception when the file exists and cannot be deleted?

我想测试这段代码抛出的异常:

private void delete(final File file, final String fileName) {
    boolean deleted = file.delete();
    if (deleted) {
        log.info("File {} was deleted", fileName);
    } else {
        throw new RuntimeException("The file exists but could not be deleted");
    }
}

我的第一个想法是创建一个在我的单元测试中无法删除的临时文件。当然,我想控制这种行为以在测试后删除该文件。但我认为这是不可能的,这是矛盾的。将文件设置为 "read only" 不适用于这种情况。

那么,有什么想法吗?

我可以创建一个新的 class 并传递删除文件和 return 布尔值的责任,这样我就可以模拟它并测试我的异常。但我想在执行此操作之前使用 Junit 和 Java 探索另一种可能性。

使用不同的文件并测试删除该文件。第二个文件的扩展名可以相同,但内容和位置可能不需要。

我认为创建临时文件或锁定文件是多余的,不需要。
文件无法删除的事实取决于托管该文件的文件系统的运行时条件。您不需要在单元测试中重现这些条件,并且除了在单元测试中重现这些条件外,并不能保证运行时使用的文件不可删除。所以我觉得单元测试不应该考虑这一点。

您可以简单地 mock/stub File.delete() 使其成为 return false 并断言 RuntimeException 被抛出:要断言的实际行为。

以 Mockito 为例:

@RunWith(MockitoJUnitRunner.class)    
public class FileServiceTest {

    @Test(expected = RuntimeException.class)
    public void myMethodToTest() throws Exception {         
        File file = Mockito.mock(File.class);
        Mockito.when(file.delete()).thenReturn(false);          
        FileService.delete(file, "test");
    }
}

编写单元测试时使用模拟对象。

获取 Mockito 并创建文件输入参数的模拟。 然后根据所需的测试结果将 delete 方法的 return 值设置为 return true 或 false。

一般来说我会做以下事情:

@RunWith(MockitoJUnitRunner.class)    
public class FileServiceTest {

    @Mock
    private File file;

    @Test
    public void myMethodToTest() {         
        doReturn(false).when(file).delete();
        try{
            FileService.delete(file, "test");
            fail("this test should throws an exception.")
        } catch (RuntimeException e) {
            assertEquals("The file exists but could not be deleted", e.getMessage());
        }        
    }
}

在此示例中,如果未抛出任何异常,则测试失败;如果遇到 RuntimeException,则验证该异常是否是您抛出的异常。