Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

People also ask

What is C mock?

CMock is an automated stub and mock generation framework made by a community of C developers, including Atom Greg Williams. It works within the Unity testing framework, and it is automatically included in any projects that use the Ceedling build management tool.

What can be mocked with MOQ?

Mock objects allow you to mimic the behavior of classes and interfaces, letting the code in the test interact with them as if they were real. This isolates the code you're testing, ensuring that it works on its own and that no other code will make the tests fail.

How do you write mock in C++?

struct SomeInterface { virtual int foo(int) = 0; }; // That's all you have to do to create a mock. Mock<SomeInterface> mock; // Stub method mock. foo(any argument) to return 1. When(Method(mock,foo)).

What is mock program?

Mocking means creating a fake version of an external or internal service that can stand in for the real one, helping your tests run more quickly and more reliably. When your implementation interacts with an object's properties, rather than its function or behavior, a mock can be used.


Edit: Install the NuGet package System.IO.Abstractions.

This package did not exist when this answer was originally accepted. The original answer is provided for historical context below:

You could do it by creating an interface:

interface IFileSystem {
    bool FileExists(string fileName);
    DateTime GetCreationDate(string fileName);
}

and creating a 'real' implementation which uses System.IO.File.Exists() etc. You can then mock this interface using a mocking framework; I recommend Moq.

Edit: somebody's done this and kindly posted it online here.

I've used this approach to mock out DateTime.UtcNow in an IClock interface (really really useful for our testing to be able to control the flow of time!), and more traditionally, an ISqlDataAccess interface.

Another approach might be to use TypeMock, this allows you to intercept calls to classes and stub them out. This does however cost money, and would need to be installed on your whole team's PCs and your build server in order to run, also, it apparently won't work for the System.IO.File, as it can't stub mscorlib.

You could also just accept that certain methods are not unit testable and test them in a separate slow-running integration/system tests suite.


Install-Package System.IO.Abstractions

This imaginary library exists now, there is a NuGet package for System.IO.Abstractions, which abstracts away the System.IO namespace.

There is also a set of test helpers, System.IO.Abstractions.TestingHelpers which - at the time of writing - is only partially implemented, but is a very good starting point.


You're probably going to have to build a contract to define what things you need from the file system and then write a wrapper around those functionalities. At that point you'd be able to mock or stub out the implementation.

Example:

interface IFileWrapper { bool Exists(String filePath); }

class FileWrapper: IFileWrapper
{
    bool Exists(String filePath) { return File.Exists(filePath); }        
}

class FileWrapperStub: IFileWrapper
{
    bool Exists(String filePath) 
    { return (filePath == @"C:\myfilerocks.txt"); }
}

My recommendation is to use http://systemwrapper.codeplex.com/ as it provides wrappers for mostly used types in System namespace


I've come across the following solutions to this:

  • Write Integration tests, not unit tests. For this to work you need a simple way of creating a folder where you can dump stuff without worrying about other tests interfering. I have a simple TestFolder class which can create a unique per test method folder to use.
  • Write a mockable System.IO.File. That is create a IFile.cs. I find using this often ends up with tests that simply prove you can write mocking statements, but do use it when the IO usage is small.
  • Examine you layer of abstraction, and extract the file IO from the class. The create a interface for this. The remainder use integration tests (but this will be very small). This differs from above in that instead of doing file.Read you write the intent, say ioThingie.loadSettings()
  • System.IO.Abstractions. I've not used this yet, but it is the one I'm most excited about playing with.

I end up using all the methods above, depending on what I'm writing. But most of the time I end up thinking abstraction is wrong when I write unit tests that hit the IO.