Someone must have done this, but I really couldn't find it. I'm talking about an IoC-friendly System.IO.File replacement. You know, unit tests shouldn't touch the file system, etc. So if your code writes a file and want to unit-test it, you pretty much have to mock the writing of the file. Except there's a known problem, System.IO.File is a static class, and those are not mockable. Even TypeMock can't mock System.IO.File since it's part of mscorlib. So the only solution left is to build an interface and a wrapper around File. So, here's the source, probably the most boring code I've ever written. I've also included a static locator that gets the IFile implementation using Ayende's IoC static accessor to the Windsor Container, so you can write code like this:
[Test] public void Copy() { var mocks = new MockRepository(); var container = mocks.CreateMock<IWindsorContainer>(); var fileImpl = mocks.CreateMock<IFile>(); IoC.Initialize(container); With.Mocks(mocks).Expecting(delegate { SetupResult.For(container.Resolve<IFile>()).Return(fileImpl); Expect.Call(() => fileImpl.Copy(null, null)) .IgnoreArguments() .Repeat.Once(); }).Verify(delegate { FileEx.Copy("source", "dest"); }); }
So you only have to replace your calls to System.IO.File to FileEx and that's it. You get the benefits of testability and extensibility (yes, sometimes you need to provide a different behavior for File.WriteAllText()) and you don't have to deal with interfaces, implementations, etc once you have set up the container. Personally, I prefer to make explicit the dependency for IFile in my components.
Like I said, I was very surprised that I couldn't find a working implementation of this... specially because there was a big debate a year ago about maintenability, YAGNI, dependency injection, coupling and more, and Anders NorĂ¥s commented this solution on one of his own posts.
Well, I hope someone finds this useful.
10 comments:
Nice, also check jayflowers doubler.
http://systemwrapper.codeplex.com does a pretty comprehensive job of wrapping most of System.IO and quite a few of the other System namespaces.
@David Keaveny: indeed, now there are a couple more that do this, but take a look at the dates.
I still like the simplicity of what you have written after reviewing my options. Thanks again for sharing.
~BuckG
FYI, the last version of JustMock can mock every method in mscorlib.
I've pushed this into nuget as mscorlib-mock (https://nuget.org/packages/mscorlib-mock/)
@Kori : nice!
~K Why the Castle Windsor dependency ?
To download, install and activate ms office setup on your device.
www.offic.com/setup
Office Setup
Office.com/setup
install ms office
www.offic.com/setup
Office Setup
Office.com/setup
install ms office
www.offic.com/setup
Office Setup
Office.com/setup
install ms office
When I initially left a comment I appear to have clicked on the -Notify me when new comments are added- checkbox and from now on every time a comment is added I get four emails with the exact same comment. Perhaps there is a way you can remove me from that service? Thanks!
Post a Comment