Tuesday 4 August 2015

How to mock file system in tests?

You are probably familiar with System.IO namespace in .NET Framework. It contains useful API for file system operations. Unfortunately, most of its methods are static and thus it is impossible to mock them. In this post I would like to show how we write testable code that works with file system.

Let's see the below simple class that copies a file to a destination directory. If the destination directory does not exist, it creates the directory and then copies the file to the destination.

In order to make our code testable we'll use System.IO.Abstractions library which can be installed from nuget:

package-install System.IO.Abstractions

It provides IFileSystem interface with all the useful interfaces on it:
It will allow us to refactor our class by injecting the IFileSystem into our constructor: As you can see from the above code, all the classes and methods on the System.IO.Abstractions are similar to those on the System.IO. So the transition is very smooth. You also noticed that the IFileSystem is injected via internal constructor, which we'll use in unit tests shortly. Public constructor will be used in our real code and it injects actual implementation of IFileSystem which is FileSystem class. The last part is the unit test. There is complementary library that contains in memory implementation of IFileSystem interface. It can be installed from nuget as well:
Install-Package System.IO.Abstractions.TestingHelpers

In addition to the implementation of IFileSystem interface, it contains convenient methods for adding files and directories (in memory, of course). So let's see how our unit test looks like: We can even assert, that the file was copied and it exists in the destination folder. The library also works well with all existing stream Read/Write operations.
Credits for the library go to: Tatham Oddie

Enjoy coding, Boris Modylevsky