I want to create unit testable code that mocks out the calls to the .Net System.IO classes, so I can really unit test instead of depending on the filesystem. I am using the SystemWrapper classes to wrap around the BCL classes.
I am trying to get a simple example working to see whether a file exists.
The problem I am having is that injecting the dependency in the class doesn't work because instantiating the dependency (through StructureMap) requires knowing what constructor parameter to pass, which won't be available at that time, also there is no default constructor.
sample code:
// don't want to create dependency here like so
//IFileInfoWrap fileInfoWrap = new FileInfoWrap(filename);
// using service locator (anti-pattern?!) since it can't be
// injected in this class
var fileInfoWrap = ObjectFactory.GetInstance<IFileInfoWrap>(
new ExplicitArguments(new Dictionary<string, object>
{
{"fileName", filename}
}));
Console.WriteLine("File exists? {0}", fileInfoWrap.Exists);
What I don't like is that the dependency is not injected, ObjectFactory should not be here (but I see no other way of creating this). The ExplicitArguments makes it messy and the argument-name is a magic-string.
For me to get this to work StructureMap config class needs to know explict which constructor I want to use ( I just started with StructureMap so this might not be the right way to set it up):
ObjectFactory.Initialize(x =>
{
x.Scan(scan =>
{
scan.AssembliesFromPath(".");
scan.RegisterConcreteTypesAgainstTheFirstInterface();
scan.WithDefaultConventions();
});
// use the correct constructor (string instead of FileInfo)
x.SelectConstructor(() => new FileInfoWrap(null as string));
// setting the value of the constructor
x.For<IFileInfoWrap>()
.Use<FileInfoWrap>()
.Ctor<string>("fileName")
.Is(@".");
});
Does anyone found a better solution to create testable code against the System.IO classes? I know part of the problem is in the design of the System.IO classes.
An approach I've used very successfully is to roll my own proxy types for the types found in System.IO
and other parts of the FCL. E.g. I want to take a dependency on System.IO.File
. I create a library called System.IO.Proxies
and add a concrete type File
and an interface IFile
. The interface IFile
exposes members equivalent to all those which I require from System.IO.File
and the concrete type implements those members by doing nothing other than forwarding method calls to System.IO.File
. System.IO.Proxies
is excluded from unit testing and code coverage. In my consuming assembly, I take a dependeny only on System.IO.Proxies
and, specifically, I only take a dependency on IFile
. This way I can mock this dependency easily and attain 100% code coverage for my consuming assembly.
(Note that this is a tailored version of my more general answer to a previous question.)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With