-5

I have a class in which a directory is created if a property is set. Now every Time I run the test the directory is created in my FileSystem. Is there a way to mock the the file/filesystem?

Class under test:

@Service("InitializeEnvironment")
public class EnvironmentChecker implements InitializingBean {


    
    @Value(value="${delivered_dir}")
    private String delivered_dir;
    
    @Override
    public void afterPropertiesSet() throws Exception {

        
        if (!StringUtils.isEmpty(delivered_dir)){
            File dir = new File(delivered_dir);
            if (!dir.exists()) {
                dir.mkdirs();
            }
        }
    }
}

UnitTest

public class EnvironmentCheckerTest {

    @Test
    public void testMailHostNichtGesetzt() throws Exception{
        EnvironmentChecker environmentChecker = new EnvironmentChecker();
        setValue(environmentChecker, "delivered_dir", "./");
        
        environmentChecker.afterPropertiesSet();

    }

    private void setValue(Object target, String fieldname, Object value){
        Field field = ReflectionUtils.findField(target.getClass(),fieldname);
        ReflectionUtils.makeAccessible(field);
        ReflectionUtils.setField(field, target, value);     
        
    }
Tushar
  • 3,527
  • 9
  • 27
  • 49
Jens
  • 67,715
  • 15
  • 98
  • 113
  • Are you looking for in-memory file systems? See discussion at http://stackoverflow.com/questions/12988135/any-available-in-memory-filesystem-implementations-for-java7-nio2 – Jayan Apr 27 '15 at 05:43
  • 2
    Jmockit can mock almost anything.. Did you try it? https://github.com/google/jimfs may work for you if you are with Java (7 or 8) – Jayan Apr 27 '15 at 05:47
  • @Jayan I have seen it. But no idea how to use it as a mock only in junit test. Not in production mode. – Jens Apr 27 '15 at 05:50
  • You can create a interface say "DirectoryCreator" with two implementations. The Unit test one will just ensure your API is called. Production version will create it. – Jayan Apr 27 '15 at 07:32
  • 1
    @Jayan No but i found a Workaround by using the Java tempfile – Jens Apr 13 '16 at 12:05

1 Answers1

2

First it's important to ask: what's the value of this test?

It may be that you've simplified your example but all the afterPropertiesSet() method does is create a directory on disk, subject to some very simple pre-conditions. The creation of a directory on the file system is a side-effect and (at least in my opinion) code with side-effects is not a good fit for unit testing.

Why? Because whether the side-effect happens or not is completely outside the scope of your application's logic. Whether it actually happens or not depends on so many things beyond your code's control - the java File api at the top, all the way down to the physical disk actually making the write on the production machine.

I'll put it another way - even if you do mock the file system, what do you gain? You gain the knowledge that a directory was written to the mock file system, and no more. What does that mean? Is it of any value? Does it give you any additional confidence about whether your system will behave as expected in production?

Any code such as this which only produces a side-effect, with only very trivial (i.e. too-simple-to-test) business logic defining whether the side-effect should happen, shouldn't be unit-tested in the first place. There's no value in it.

If in your actual code there's complex business logic determining whether a side-effect happens, then my advice is to abstract away the code producing the side-effect into another class. Then, you can easily mock it in your existing class to test the 'pure' business logic around it.

Please let me emphasise that I'm not advocating that side-effects such as this shouldn't be tested at all. I'm just saying that unit tests are the wrong method for testing them. Instead, go with automated (or manual!) integration tests on production hardware.

davnicwil
  • 28,487
  • 16
  • 107
  • 123