2

I would like to test the exception trowed by this piece of code:

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

My first idea was create a temporary file that can't be deleted in my unit test. For sure, I would like to control this behavior to delete this file after the test. But I supposed that this is not possible, it's contradictory. Set the file to "read only" not works for this case.

So, any ideas?

I could create a new class and pass the responsibility to delete the file and return the boolean, so I could mock it and test my exception. But I would like to explore another possibilities using Junit and Java before do this.

Dherik
  • 17,757
  • 11
  • 115
  • 164
  • Using a lock should prevent the file to be deleted. So this should do the trick. – AxelH Apr 19 '18 at 13:03
  • Can you open/lock the file? It should throw exception then. – achAmháin Apr 19 '18 at 13:04
  • I could't find the question that already exists about this subject. Thanks! – Dherik Apr 19 '18 at 13:12
  • 1
    Really not a duplicate. The duplicate is a way to solve the problem but I don't think that it addresses the question in a general way. – davidxxx Apr 19 '18 at 13:13
  • 1
    Related link about the problem (not duplicated): https://stackoverflow.com/questions/128038/how-can-i-lock-a-file-using-java-if-possible – Dherik Apr 19 '18 at 15:40

4 Answers4

1

I think that creating a temporary file or locking a file is overkill and not required.
The fact that a file cannot be deleted depends on runtime conditions on the filesystem where this file is hosted. You don't need to reproduce these conditions in your unit test and besides reproducing these conditions in the unit test will not guarantee you that the file used at runtime will be not deletable. So I think that this point should not be considered in the unit test.

You could simply mock/stub File.delete() to make it return false and assert that a RuntimeException is thrown : the actual behavior to assert.

With Mockito for example :

@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");
    }
}
davidxxx
  • 125,838
  • 23
  • 214
  • 215
1

Use mock objects when writing unit tests.

Get Mockito and create a mock of the file input parameter. Then set the return value of the delete method on your mock to return true or false based on the desired test outcome.

DwB
  • 37,124
  • 11
  • 56
  • 82
1

In general I would do the following:

@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());
        }        
    }
}

On this example the test fails in case it doesn't throw any exception and, in case it gets a RuntimeException, it verify if that exception is the one you throw.

Eduardo Meneses
  • 504
  • 3
  • 18
0

Use a different file and test deletion on that file. The extension could be the same for the second file, but the content and location may not need to be.

Raymo111
  • 514
  • 8
  • 24