There are often times when you want to include static services in your code. For example, when accessing the file system or including an external analytics package. When you do, it presents a testability problem. Every time you exercise the code via a test, that static service is also called. This post explains a simple pattern I use to solve this issue.
The problem code
https://gist.github.com/codescribler/fa7f4e3b87f1973382c0
The issue here is that every time a test runs this code it must interact with the file system to ensure it is in the state expected for the test. At best this is going to be slow but at worst can yield incorrect results. What if the someone is already creating files in that folder or it becomes unavailable or the account running the test does not have the required permissions (this list of possible issues goes on and on). The most valuable tests you can write here are ones to ensure the logic is executes as expected, in this case to throw an exception if the file already exists or to write the data to the file if it does not. You could of course go to town and check the parameters and catch various exceptions but for this post I’ll ignore those possibilities.
The wrapper object
Step 1 – Define the interface
A simple approach to solving this problem is to use a wrapper object. Start off by identifying the ‘services’ you need from the static class. In this case you will need a ‘FileExists’ method that returns a bool and a WriteAllText which is a void. Clearly the static class has many more methods but you should only implement the ones you actually use. This way you minimise the code any implementer of your interface must write. This should lead you to an interface that looks something like this:
https://gist.github.com/codescribler/0a46a453e1d5990f0929
Step 2 – Implement the concrete class
The implementation of the actual class is then very simple. Just pass the call down to the original static class methods.
https://gist.github.com/codescribler/2b4be15884a42e7913c0
Step 3 – Inject your new service into the original class
The final step is to simply adjust the original class to use your interface rather than the static class directly. This gives you the option of swapping out the actual implementation so that in production the code uses the wrapped class while during test you can inject a fake.
https://gist.github.com/codescribler/cfaeaf94b086c2112dad
By programming against your new interface you have removed the direct dependency on the static class and made your class easy to test.