tags:

views:

72

answers:

2

This is probably crazy.

I want to take the idea of Dependency Injection to extremes. I have isolated all System.IO-related behavior into a single class so that I can mock that class in my other classes and thereby relieve my larger suite of unit tests of the burden of worrying about the actual file system.

But the File IO class I end up with can only be tested with integration tests, which-- of course-- introduces complexity I don't really want to deal with when all I really want to do is make sure my FileIO class calls the correct System.IO stuff. I don't need to integration test System.IO. My FileIO class is doing more than simply wrapping System.IO functions, every now and then it does contain some logic (maybe this is the problem?).

So what I'd like is to be able to test my File IO class to ensure that it makes the correct system calls by mocking the System.IO classes themselves. Ideally this would be as easy as having a constructor like so:

    public FileIO(
        System.IO.Directory directory, 
        System.IO.File file, 
        System.IO.FileStream fileStream
    )
    {
        this.Directory = directory;
        this.File = file;
        this.FileStream = fileStream;
    }

And then calling in methods like:

    public GetFilesInFolder(string folderPath)
    {
        return this.Directory.GetFiles(folderPath)
    }

But this doesn't fly since the System.IO classes in question are static classes. As far as I can tell they can neither be instantiated in this way or subclassed for the purposes of mocking.

+4  A: 

Make a class which contains functions which simply redirect to System.IO. Make another class that is faking/mocking System.IO. Have both of these classes implement a common interface. Then you don't have to worry about the fact that System.IO is full of statics.

Billy ONeal
+1  A: 

Whenever you want to shield yourself from framework internal stuff that you don't want in your design, simply write a ideal interface as you want it. Meaning, if you only need File.Exists(), File.Delete() and File.OpenRead() then write a simplistic interface that only has these methods you actually need.

After that, you write a wrapper class around the actual framework implementation that implements your interface and successfully hides the framework goo you try to get away from.

I did this on the dotless project with most of the HttpContext stuff that is accessed through static variables. You can see an example of this here:

http://github.com/dotless/dotless/blob/master/src/dotless.Core/Abstractions/IResponse.cs

IResponse is my simplistic interface that does exactly what I need it to do. The code inside CssResponse can be tested through integration tests, but for now I just assume it works since I never touched it and it's fairly simple. Whenever I need to test a class utilizing the IResponse interface I simply inject a mock object or a fake.

greetings Daniel

Tigraine