在JUnit中删除文件和目录

12

我正在编写一个测试方法,用于在目录中创建文件。以下是我的JUnit测试代码:

  @Before
  public void setUp(){
      objectUnderTest = new ClassUnderTest();
      //assign another directory path for testing using powermock
      WhiteBox.setInternalState(objectUnderTest, "dirPathField", mockDirPathObject);

      nameOfFile = "name.txt";
      textToWrite = "some text";
  }

  @Test
  public void shouldCreateAFile(){


      //create file and write test
      objectUnderTest.createFile(nameOfFile, textToWrite);
      /* this method creates the file in mockPathObject and performs
         FileWriter.write(text);
         FileWriter.close();
      */

      File expect = new File(mockPathObject + "\\" + nameOfFile);
      assertTrue(expect.exist());

      //assert if text is in the file -> it will not be called if first assert fails
  }

  @After
  public void tearDown(){
       File destroyFile = new File(mockPathObject + "\\" + nameOfFile);
       File destroyDir = new File(mockPathObject);

       //here's my problem
       destroyFile.delete(); //why is this returning false?
       destroyDir.delete(); //will also return false since file was not deleted above

  }

我能够使用deleteOnExit()删除文件,但我不能使用delete或deleteOnExit删除目录。在这个测试脚本中,我还将执行其他测试,因此不想使用deleteOnExit。
我不知道为什么在JUnit测试脚本中无法删除它,而当代码不是JUnit测试时,可以删除由FileWriter创建和修改的文件。我还尝试在测试方法后执行一个无限循环,并手动删除该文件,但它告诉我其他程序仍在使用该文件,尽管我能够修改其内容。
希望有人能建议一种删除测试期间创建的文件和目录的方法。谢谢:D
为了更清晰,我要测试的方法看起来像这样 调用FileWriter的单元测试方法 编辑:这是要测试的方法
    public void createFile(String fileName, String text){

           //SOME_PATH is a static string which is a field of the class
           File dir = new File(SOME_PATH); //I modified SOME_PATH using whitebox for testing

           if(!dir.exists()){
                booelan createDir = dir.mkdirs();
                if(!createDir){
                           sysout("cannot make dir");
                           return;
                }
           }


           try{
                 FileWriter fileWrite = new FileWriter(dir.getAbsolutePath() + "/" + fileName, true);
                 fileWrite.write(text);
                 fileWrite.close();
           }
           catch(Exception e){
                 e.printStackTrace();
           }

    }

我无法修改这个方法,因为它是由其他开发人员创建的。我的任务只是按照指示为测试自动化创建单元测试。谢谢。


1
你确定 objectUnderTest.createFile(nameOfFile, textToWrite); 释放了所有资源,即关闭了任何相关的流/写入器吗? - A4L
objectUnderTest.createFile(nameOfFile, textToWrite); 在创建并写入文件后执行 FileWriter.close()。我还尝试在 tearDown 中执行 objectUnderTest=null,但仍无法删除该文件。 - Frank Smith
我会为每个测试使用不同的文件名。你可以用计数器生成名称。 - Peter Lawrey
我认为即使我使用deleteOnExit()删除了这些文件,但由于我无法使用单个文件删除目录,因此仍然无法删除该目录。 - Frank Smith
1
让我们看看 objectUnderTest.createFile 如何处理/关闭 FileWriter。 - davidmontoyago
我也遇到了同样的问题,在阅读了A4L的建议后,我开始检查与该文件相关联的每个输入和输出流:一旦我确保每个流都关闭了,我就可以在tearDown方法中删除该文件! - yvolk
4个回答

14

使用@Rule注解和TemporaryFolder类来代表需要删除的文件夹。

http://kentbeck.github.com/junit/javadoc/4.10/org/junit/Rule.html(404找不到)

更新用法示例,请参考http://junit.org/junit4/javadoc/4.12/org/junit/rules/TemporaryFolder.html

public static class HasTempFolder {

  @Rule
  public TemporaryFolder folder= new TemporaryFolder();

  @Test
  public void testUsingTempFolder() throws IOException {
    File createdFile= folder.newFile("myfile.txt");
    File createdFolder= folder.newFolder("subfolder");
    // ...
  }

}

1
我认为我不能使用TemporaryFolder,因为我正在测试的方法是创建文件夹和文件的方法。 - Frank Smith
2
你能否将要创建的文件夹放在TemporaryFolder中作为子文件夹吗?例如:mockDirPath是TemporaryFolder的子文件夹。 - Colin D
也许吧,只要我不修改被测试的类。我会尝试并希望 temporaryFolder 下的文件在测试后会被删除 :D。感谢您的建议。 - Frank Smith

8
这是我通常清理文件的方法:
@AfterClass
public static void clean() {
    File dir = new File(DIR_PATH);
    for (File file:dir.listFiles()) {
        file.delete();
    }
    dir.delete();
}

为了删除目录,你的文件夹必须为空,确保没有其他测试方法在那里创建更多的文件。

确保你在finally块中关闭FileWriter实例


是的,但问题在于,即使我确定在测试方法中关闭了FileWriter,我仍然无法删除该文件。如果我使用deleteOnExit删除文件,我也无法执行此操作。 - Frank Smith

3

请确保方法objectUnderTest.createFile(nameOfFile, textToWrite)实际上关闭了打开的任何流?


2
objectUnderTest.createFile(...) 在创建并写入文件后执行 FileWriter.close(); - Frank Smith

0

我认为最好的方法是在JVM退出后进行删除:

Path tmp = Files.createTempDirectory(null);
tmp.toFile().deleteOnExit();

关于deleteOnExit的警告:如果您频繁调用deleteOnExit来删除临时文件,并且您的应用程序运行时间很长,例如JBoss应用服务器,则可能会出现OutOfMemory错误,因为VM正在跟踪一个非常长的要在System.exit时删除的文件列表,但该事件并未发生。 - DuncG

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接