How to including static services in a testable way

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

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:

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.

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.

By programming against your new interface you have removed the direct dependency on the static class and made your class easy to test.

Daniel

I'm a professional software engineer of near on 15 years. Lucky enough to work for a small but rapidly growing company in London called Redington. They have given me the technical freedom to learn some cutting edge technologies like CQRS and Event Sourcing. Now I'm sharing what I learn here.