File system mocking for the lazy programmer
Monday, December 3, 2007 – 2:25 PMUntil now I’ve always skipped mocking or stubbing out the .NET file system File/Path/Directory classes and just had tests that interacted with the disk. Largely because I was too lazy to mock out the file system. I would simply use the real file system and deal with the pitfalls and limitations.
Using the real file system can cause tests to be order dependent. Tests should never be order dependent. One test writes a file and forgets to delete it for example. The end result is you spend more time worrying about test cleanup. It also makes it hard to write tests against code that wants to use things like system files – not something you want your tests messing with.
Turns out that while I’m lazy Brad Wilson isn’t. I actually wrote a pretty complete facade to the .NET framework’s file system classes while writing the CodePlex Source Control Client. I stumbled across the code while looking for something else and promptly “stole” it – the code is distributed under the Microsoft Public License. You need the following files from the source code download:
MockFileSystem.cs
EncryptionUtil.cs
FileSystem.csĀ
IFileSystem.cs
Reference.cs (copy the definition of ItemType to a new file)
Your project will also need a reference to the System.Security.dll and you’ll probably want to fix up the namespaces.
You can then write tests like this:
public class MyConfigLoader { public static readonly string FilePath = @"C:\System32\myapp.config"; IFileSystem _fileSystem; public MyConfigLoader(IFileSystem fileSystem) { _fileSystem = fileSystem; } public void Load() { if (!_fileSystem.FileExists(MyConfigLoader.FilePath)) { _fileSystem.WriteAllText(MyConfigLoader.FilePath, "<myConfig></myConfig>"); } } } public class MyConfigLoaderFixture { [Fact] public void TestThatTheConfigLoaderWritesABlankFile() { IFileSystem fileSystem = new MockFileSystem(); MyConfigLoader target = new MyConfigLoader(fileSystem); target.Load(); Assert.True(fileSystem.FileExists(MyConfigLoader.FilePath)); } }
This is a very trivial example but you get the idea.
3 Responses to “File system mocking for the lazy programmer”
I often need to mock out the filesystem, but find it of little use to simply duplicate the filesystem api. Rather, I would treat the filesystem as a service, and make an interface that represented that service.
The result is a much higher level interface that allows the code to read much more clearly. (Instead of mocking the filesystem, I mock the service).
By Steve Campbell on Dec 5, 2007