Tutorial :Needed: File system interfaces and implementation in .NET [duplicate]



Question:

Possible Duplicate:
How do you mock out the file system in C# for unit testing?

I write unit tests to my code, using Moq as a mocking framework.
My code includes calls to the file system, using direct calls to System.IO classes. For instance, File.Exists(...) etc.
I'd like to change that code to be more testable, so I should have an interface, say IFile, with a relevant method, say Exists(string path).
I know I can write it from scratch, but I thought that maybe there's a complete, robust framework that has both interfaces and implementations for the file system. This (desired) framework may also be some kind of a "service", and therefore its API doesn't have to be an "interface equivalent" to the System.IO namespace.
Note that I'd really like to have interfaces (and not static methods) so that my code is ready for dependency injection

What I got so far:

  • A somehow similar, yet not the same question was asked in stackoverflow
  • In codeplex.com there's a project named CodePlex Source Control Client (link) that has such classes in the source code (see /Source/TfsLibrary/Utility/ in the source code for specific details)

Any other recommendations?


Solution:1

I've written adapters for the static System.IO.File and Directory methods. Then in my classes I do the following:

public class MyService {    public IFile File {private get;set;}    public MyService() {      File = new FileImpl();    }    public void DoSomething() {      File.ReadAllText("somefile");    }  }  

Then you can inject a mock as IFile for testing.


Solution:2

Alright, I don't have the file-system-mock library you wish for (though it may be out there somewhere and would be cool), but this may help. One of the interesting concepts the "behaviorist" school of unit testing thought has come up with is the idea of an "outgoing interface". In some cases, there seems to be as much value in taking the calls an object makes to the entire universe of things outside of itself, and turning them into an interface, as there is in the typical act of making an interface for methods the outside world can call on your object).

In this case, you might consider, instead of mocking the entire file system, making one or more logically coherent interfaces for the answers and services your object needs from the outside world. The calls would merely answer the questions you need answered ... not dictate implementation. Then, you can use dependency injection as you mentioned to inject in the implementation you desire for your tests. And you'll probably use Moq to do so since you're familiar with it.

So, your "outgoing interface" might have a method called DoesFileExist(). It might accept a path. Or, if there is a "higher level" business question your object is trying to answer, and seeing if a file exists is merely the way that question is answered, then your outgoing interface might not have a method about file existence at all. It might instead be something like "DoIAppearToHaveAccessToTheFileServer", or even "IsThereAPreviouslySavedGame".

This is some work, but might be truer to the principles of good unit testing ... let your object-under-test express what it is trying to do, and let your unit tests test it and only it. Just a thought ... hope it helps.


Solution:3

I maintain the Jolt.NET project on CodePlex, which contains a library to generate such interfaces and their implementations for you. Please refer to the Jolt.Testing library for more information.


Solution:4

http://systemwrapper.codeplex.com/ offers a good selection, although I haven't tried it yet. It looks like the author could use some help with completing the project.


Solution:5

I understand that the Typemock package can do things like this.


Solution:6

Rather than mock the file system interface, I'd traditionally opt to mock the Filesystem itself. This is a relatively easy task on any serious OS. You can build a userspace filesystem very easily with Mono.Fuse, a C# implementation of FUSE, Filesystems in USErspace. I'm not sure what if any porting would be required to get Dokan, FUSE for Windows, but FUSE works fine on Linux, OSX, and Solaris.


Note:If u also have question or solution just comment us below or mail us on toontricks1994@gmail.com
Previous
Next Post »