Generalizing the "hole in the middle" pattern can be a good way to make a method that at first blush appears to be unsuited to unit testing into a fully testable one.
Consider the code
which is intended to find the
app.config file for a service, and extract the WCF endpoint listening port from it. Now, even given a fully mocked
ServiceInstallPath() -- assume that involves a
protected abstract method somewhere in its body so we can
PartialMock that -- there is a problem with that direct access to the filing system in the middle.
Well, this is something where we essentially turn the "hole-in-the-middle" around. Adjust the sequence to create the
XmlDocument before looking at the file, and do an Extract Method to get
And now we replace the explicit
GetFileStream with a
Func<string, Stream> or an equivalent delegate type passed in as an argument
to give us a couple of new one-liner methods which can safely be tested by inspection, and the previously untestable core functionality in the newly refactored and, most importantly, functional method is now fully testable.
Yes, the code here is raw but now we have separated out all the real work, so that can be tested to destruction (and extended to handle all the
IOException cases which the original method just falls over with). The unit test fixture can provide its own
Func<string, Stream> implementations that can both assert that the path is correctly constructed and can provide an arbitrary mocked stream to drive the XML parsing through various states, without having to worry about what is happening -- or not -- to the filing system.