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.
12 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!
Thank you so much for sharing this great blog. Very inspiring and helpful too much. Body Sculpting
Hi. None of the links working now. Yes, There are System.IO.Abstractions, bot some old projects doesn't have it and cant upgrade, so your solution can still be useful
Post a Comment