mat_boy
mat_boy

Reputation: 13698

Path of saved file in a unit test with Junit

In a Java application, I have a method of a class that saves a file just using its name.

public void doSomething(){
    final File file = new File("XXX"+(new Random().next())+".txt");
    file.createNewFile();
}

Then, in a unit test with JUnit 4, I run the class that execute the method and I see a file created with name XXX.txt in the root folder of the project.

@Test
public void doSomethingTest() throws Exception{
  //call doSomething();
  Path path = //to project folder
  Files.delete(path);
}

How can I get this path dynamically such that I can use a @After method to delete it?

Upvotes: 0

Views: 10356

Answers (4)

JB Nizet
JB Nizet

Reputation: 692231

The simplest way to do is to make your code testable by allowing it to inject the base directory where to create files.

Instead of

public Foo() {
}

public void doSomething() {
    final File file = new File("XXX" + (new Random().next()) + ".txt");
    file.createNewFile();
}

Use

private File baseDirectory;

public Foo() {
    this(new File("."));
}

public Foo(File baseDirectory) {
    this.baseDirectory = baseDirectory;
}

public void doSomething() {
    final File file = new File(baseDirectory, "XXX" + (new Random().next()) + ".txt");
    file.createNewFile();
}

Now your test can create a temporary empty directory, pass it to the constructor, call the method, check the files and delete them after the test.

This is probably a feature you would want anyway, because always writing in the current directory doesn't seem like a good idea to me.

Upvotes: 8

Alexey Gavrilov
Alexey Gavrilov

Reputation: 10853

I recommend, as was already suggested, to change the source code and pass the parent folder from outside, preferably in the class constructor.

If for some reason you cannot do it, then you can try to override the user.dir system property which controls the current working directory, that is where your files will be created by default.

Note that the user.dir is global, so changing it will affect all the classes. For example, you won't be able to run your test concurrently.

Also in JUnit you can use the TemporaryFolder rule which would create a temporary directory before the test starts and delete it after the test finishes.

Example (copy-paste from the javadoc):

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");
         // ...
     }
}

Upvotes: 4

Eswar Goud
Eswar Goud

Reputation: 132

You can use Apache's commons-io. It has a FileUtils class that will do what you want.

Here is an example , implementation and its test `

import java.io.File;
import java.io.IOException;

public class FileSave {

    public static void main(String[] args) throws IOException {
        FileSave fileSave = new FileSave();

        fileSave.saveFile("test.txt");
    }

    public void saveFile(String fileName) throws IOException {
        final File file = new File(fileName);
        file.createNewFile();
        System.out.println("Hello");
    }
}

`

Test file

`

import java.io.File;

import org.apache.commons.io.FileUtils;
import org.junit.Assert;
import org.junit.Test;

public class FileSaveTest {


    @Test
    public void checkFileSaved() throws Exception{
        FileSave fileSave = new FileSave();
        fileSave.saveFile("test.txt");
        Assert.assertTrue(FileUtils.deleteQuietly(new File("test.txt")));
        System.out.println();
    }
}

`

the method FileUtils.deleteQuietly will return true when it delete , otherwise false.

Upvotes: 0

chrisl08
chrisl08

Reputation: 1658

You can use file.getAbsolutePath() to get the complete file path, expose it as a method and then delete it in the junit test.

Upvotes: 0

Related Questions