I'm using a temporary folder in my unit test using the #Rule of JUnit.
The folder is not being deleted after the tests finish
Java version : 1.8
JUnit version: 4.12
Os windows 10
I'm creating a file.csv under a temp folder in order to edit it using CSVPrinter from org.apache.commons
public class MyService {
public void createCSVFile(String basePath) {
try (FileWriter out = new FileWriter(format("%s/file.csv", basePath));
CSVPrinter printer = new CSVPrinter(out, CSVFormat.DEFAULT.withHeader(HEADERS))) {
//printer.PrintRecord(args);
} catch (IOException e) {
log.error("Failed to create file.csv under " + basePath, e);
}
}
}
The test:
#Rule
public TemporaryFolder folder = new TemporaryFolder();
private String folderPath;
private MyService myService;
#Before
public void setup() throws IOException {
folder.newFile("file.csv");
folderPath = folder.getRoot().getPath();
}
#Test
public void testing_myService() {
myService.createCSVFile(folderPath);
//Assert
}
When i open the folder ex: C:\Users\me\AppData\Local\Temp\junit2290989758736528709
I can still see the file.csv as it was not deleted
I tried to migrate the create of the file to become in the tests. It did not fix it
#Test
public void testing_myService() {
folder.newFile("file.csv");
myService.createCSVFile(folder.getRoot().getPath());
//Assert
}
I added an #After method to delete the folder
#After
public void cleanup() throws IOException {
//Tried several ways to delete the folder and file as well
//FileUtils.forceDelete(folder.getRoot().getAbsoluteFile());
//folder.getRoot().delete();
//FileUtils.deleteDirectory(folder.getRoot());
//new File(folderPath +"/file.csv").delete();
//All methods did not delete neither the direcotry (with exception can't delete file.csv) nor deleted the file.csv
}
I also tried to call the folder.create(); and folder.delete(); myself without using the #Rule
But the folder wasn't deleted as well
The file.csv and folder are marked as read-only when viewing the properties on windows
I tried to change that in the code
folder.setWritable(true);
folder.setReadable(true);
folder.setExecutable(true);
Didn't manage to delete the folder as well
My aim is to find a solution that works for any environment where the code is checked out ex: CI pipeline on a linux server and on windows
any other reason for this behavior?
I suspect that some code is holding a file handle, preventing the temporary directory from being deleted.
I suggest:
#Rule
public final TemporaryFolder folder = TemporaryFolder.builder()
.assureDeletion()
.build();
That should cause TemporaryFolder to throw an exception if it could not delete the folder.
You should probably be creating and deleting in a folder within your project structure.
But it's probably not working because of a permission issue:
Either change the permissions of the folder so that the program has priveledges to delete, or run the program/IDE as an administrator.
That should fix the problem.
Related
I am trying to write a JUnit test for a java code that with three methods.
FileDeletion.java:
public static void fileDeletion(String filePath) {
File file = new File(filePath);
file.delete();
}
I looked online on how to test this, but it came up with how to make a temporary file in JUnit which is "guaranteed to be deleted after the test finishes".
See: https://howtodoinjava.com/junit/junit-creating-temporary-filefolder-using-temporaryfolder-rule/
How do I make a file which can be created and then subsequently deleted in a JUnit Test?
Any help would go a long way, many thanks.
I would consider using JUnit's TemporaryFolder rule to help you set up the file and directory structure you need for your test which is cleaned up after your test.
public class DeleteFileTest {
#Rule
public TemporaryFolder folder = new TemporaryFolder();
#Test
public void test() {
final File file = folder.newFile("myfile1.txt");
file.delete();
//Assert
}
}
I found two ways to create temporary directories in JUnit.
Way 1:
#Rule
public TemporaryFolder tempDirectory = new TemporaryFolder();
#Test
public void testTempDirectory() throws Exception {
tempDirectory.newFile("test.txt");
tempDirectory.newFolder("myDirectory");
// how do I add files to myDirectory?
}
Way 2:
#Test
public void testTempDirectory() throws Exception {
File myFile = File.createTempFile("abc", "txt");
File myDirectory = Files.createTempDir();
// how do I add files to myDirectory?
}
As the comment above mentions, I have a requirement where I want to add some temporary files in these temporary directories. Run my test against this structure and finally delete everything on exit.
How do I do that?
You can do it the same way you do it for real folders.
#Rule
public TemporaryFolder rootFolder = new TemporaryFolder();
#Test
public void shouldCreateChildFile() throws Exception {
File myFolder = rootFolder.newFolder("my-folder");
File myFile = new File(myFolder, "my-file.txt");
}
Using new File(subFolderOfTemporaryFolder, "fileName") did not work for me. Calling subFolder.list() returned an empty array. This is how I made it work:
#Rule
public TemporaryFolder temporaryFolder = new TemporaryFolder();
#Test
public void createFileInSubFolderOfTemporaryFolder() throws IOException {
String subFolderName = "subFolder";
File subFolder = temporaryFolder.newFolder(subFolderName);
temporaryFolder.newFile(subFolderName + File.separator + "fileName1");
String[] actual = subFolder.list();
assertFalse(actual.length == 0);
}
Using TemporaryFolder creates a directory with a common root. Once you have created a folder, you can then create a file by specifying the directory structure and the final filename as the name.
#Rule
public TemporaryFolder rootFolder = new TemporaryFolder();
#Test
public void shouldCreateChildFile() throws Exception {
File myFolder = rootFolder.newFolder("my-folder");
File myFileInMyFolder = rootFolder.newFile("/my-folder/my-file.txt");
}
You can create child directories in the same way.
There two ways to delete temp directory or temp file.Fist,delete the dirctory or file manually use file.delete() method,Second,delete the temp directory or file when program exis user file.deleteOnExist().
You can try this,I print the path to console,you can to check realy delte or not,I test on windows7 system.
File myDirectory = Files.createTempDir();
File tmpFile = new File(myDirectory.getAbsolutePath() + File.separator + "test.txt");
FileUtils.writeStringToFile(tmpFile, "HelloWorld", "UTF-8");
System.out.println(myDirectory.getAbsolutePath());
// clean
tmpFile.delete();
myDirectory.deleteOnExit();
I am trying to test a method that copies a source file to a dest file using JUnit's TemporaryFolder. I get a Java IOException when I try run this test however. Does it matter where I make the declaration for the folder? (My test class has several different tests in it). And if so, what is the proper way to do it? I ask because I currently have several unit tests above this code, then I try to set up the testing for the file copying. Maybe the #Rule-#Before-#Test block needs to be in its own class? Here is the snippet where I have coded the test:
...other tests...then:
#Rule
public static TemporaryFolder tmp = new TemporaryFolder();
private File f1, f2;
#Before
public void createTestData() throws IOException {
f1 = tmp.newFile("src.txt");
f2 = tmp.newFile("dest.txt");
BufferedWriter out = new BufferedWriter(new FileWriter(f1));
out.write("This should generate some \n" +
"test data that will be used in \n" +
"the following method.");
out.close();
}
#Test
public void copyFileTest() {
out.println("file 1 length: " + f1.length());
try {
copyFile(f1, f2);
} catch (IOException e) {
e.getMessage();
e.printStackTrace();
}
if (f1.length() != f2.length())
fail();
else if (!f1.equals(f2))
fail();
assertSame(f1, f2);
}
When I run this test class, all 11 of my tests now fail (which previously passed) and I get java.io.IOException: No such file or directory.
So looking at the JUnit Javadoc, I have found out that any declaration under #Rule must be public, and not static. So I took out the static and just have:
#Rule
public TemporaryFolder tmp = new TemporaryFolder();
I still do not know for sure if it matters where this declaration is made when you have other unit tests in your class that do not use the #Rule declaration, but this did allow me to run through my tests successfully.
If you really want to declare TemporaryFolder as static, you can use #ClassRule which is used to annotate static fields that contains Rule.
#ClassRule
public static TemporaryFolder tmp = new TemporaryFolder();
Reference: http://junit-team.github.io/junit/javadoc/4.10/org/junit/ClassRule.html
I'm writing a test for a method that creates a file in a directory. Here's what my JUnit test looks like:
#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
}
I was able to delete the File using deleteOnExit() but I will not be able to delete the directory using delete or deleteOnExit. I will also perform other test for other scenarios in this test script so I don't want to use deleteOnExit.
I don't know why I cannot delete it in JUnit test script while I can delete a file created and modified by FileWriter in runtime when the code is not a JUnit test. I also tried performing an infiniteLoop after the test method and delete the file manually but it tells me that other program is still using the file though I'm able to modify its content.
Hope somebody can suggest a way to delete the files and directories created during the tests. Thanks :D
For more clarity, the method I test looks like this Unit testing method that invokes FileWriter
Edit:Here is the method to test
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();
}
}
I cannot modify this method as other developers created it. I was just instructed to create unit tests for test automation. Thanks.
Use the #Rule annotation and the TemporaryFolder classfor the folder that you need to delete.
http://kentbeck.github.com/junit/javadoc/4.10/org/junit/Rule.html (404 not found)
Update example of usage by 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");
// ...
}
}
This is how I usually clean up files:
#AfterClass
public static void clean() {
File dir = new File(DIR_PATH);
for (File file:dir.listFiles()) {
file.delete();
}
dir.delete();
}
Your directory must be empty in order to delete it, make sure no other test methods are creating more files there.
Ensure you are closing the FileWriter instance in a finally block.
Ensure that the method objectUnderTest.createFile(nameOfFile, textToWrite) actually closes any opened streams?
I think the best approche is te delete after JVM exit :
Path tmp = Files.createTempDirectory(null);
tmp.toFile().deleteOnExit();
I'm creating a TemporaryFolder using the #Rule annotation in JUnit 4.7. I've tried to create a new folder that is a child of the temp folder using tempFolder.newFolder("someFolder") in the #Before (setup) method of my test. It seems as though the temporary folder gets initialized after the setup method runs, meaning I can't use the temporary folder in the setup method. Is this correct (and predictable) behavior?
This is a problem in Junit 4.7. If you upgrade a newer Junit (for example 4.8.1) all #Rule will have been run when you enter the #Before method:s. A related bug report is this: https://github.com/junit-team/junit4/issues/79
This works as well. EDIT if in the #Before method it looks like myfolder.create() needs called. And this is probably bad practice since the javadoc says not to call TemporaryFolder.create(). 2nd Edit Looks like you have to call the method to create the temp directories if you don't want them in the #Test methods. Also make sure you close any files you open in the temp directory or they won't be automatically deleted.
<imports excluded>
public class MyTest {
#Rule
public TemporaryFolder myfolder = new TemporaryFolder();
private File otherFolder;
private File normalFolder;
private File file;
public void createDirs() throws Exception {
File tempFolder = myfolder.newFolder("folder");
File normalFolder = new File(tempFolder, "normal");
normalFolder.mkdir();
File file = new File(normalFolder, "file.txt");
PrintWriter out = new PrintWriter(file);
out.println("hello world");
out.flush();
out.close();
}
#Test
public void testSomething() {
createDirs();
....
}
}