I'm using AutoFixture to test some code that uses System.IO.Abstractions.IFileSystem
.
I also have some code that uses IFileInfo
and IDirectoryInfo
. When I create my AutoFixture Fixture
object, I need to accomplish a couple of things:
IFileSystem
parameters to be automatically given a frozen (singleton) instance of MockFileSystem
.IFileInfo
instances need to originate from MockFileSystem
via MockFileSystem.FileInfo.FromFileName()
somehow. If there's a way to take an existing IFileInfo
that AutoFixture created and replace it, I can use the FullName
property to pass to MockFileSystem so that it's connected to that instance.IDirectoryInfo
instances to originate from MockFileSystem
.I personally find the AutoFixture customization system very confusing and lacks proper documentation. There's pieces of information out there but I'm not sure how to accomplish my goals.
As I struggled through solving my own problem, I eventually came up with this class:
public class MockFileSystemSpecimenBuilder : ICustomization
{
public void Customize(IFixture fixture)
{
var fs = new MockFileSystem();
fixture.Inject(fs);
fixture.Customize<IFileInfo>(x => x.FromFactory(() =>
{
var name = $"MockFile-{fixture.Create<string>()}";
return fs.CurrentDirectory().File(name);
}));
fixture.Customize<IDirectoryInfo>(x => x.FromFactory(() =>
{
var name = $"MockDirectory-{fixture.Create<string>()}";
return fs.CurrentDirectory().SubDirectory(name);
}));
}
}
I add it to my Fixture
class after its created in my factory method:
public static Fixture Create()
{
var fixture = new Fixture
{
OmitAutoProperties = true
};
fixture
.Customize(new AutoNSubstituteCustomization {ConfigureMembers = true})
.Customize(new MockFileSystemSpecimenBuilder());
return fixture;
}
One thing I really enjoy about this solution is that I do not need to explicitly Freeze()
the IFileSystem
type anymore. The mock filesystem is intrinsic to this fixture so I always get correct file system behavior. This ends up being less error prone and more convenient.