As you all know the key to make a class testable is to make all its dependencies replaceable with test doubles. This is usually done by using Dependency Injection and implementing interfaces. However, from time to time you have dependencies on third party code that you cannot change and that might not implement an interface. In that case you cannot replace it with a test double and you end up with untestable code, which is bad. I came across such code last week and want to show you how you can turn most third party dependencies injectable and create code that can be tested. The code I found looked something like this.
Its purpose is very simple; it should make sure a certain directory exists on an ftp server. To test this code I always need to setup the ftp server and create some defined directories and run the code against this ftp server, because I am not able to replace the SftpClient with a mock, which returns what I want without actually calling the server.
Step 1: Dependency Injection
The first thing you need to do to get rid of the dependency is to inject it and store it in an instance variable. This is not only the first step to make the code testable but it additionally allows you to specify where the server is located and where the credentials come from, since you inject the whole client. The result of this step looks like this.
Step 2: Derive from dependency and create your own interface
The next step is to create your own class that does nothing more than derive from your dependency, implements an empty interface and overrides your dependencies constructors. Now you have a class, that has the same capabilities as your dependency because of the inheritance, but it implements an interface and is there for replaceable. The original client had five constructors, but I just implemented the one that I was using, which is usually enough. To check that everything still works you can replace your dependency in your code with the newly created implementation, recompile and manually test your application (or run your integration / system tests if you have them). The result looks like this.
Step 3: Define the interface
The last step is to replace the dependency in your code with the newly created empty interface. Your compiler or IDE will now tell you which methods are missing and you can create those method signatures in your interface. Since those signatures will match your original dependency and your custom class derives from it, you don’t even need to write a single line of code in your custom class to make it compile again. With the interface in place you are now ready to create test doubles based on that interface, inject into your code and create a rich suite of tests ;-). The final result looks like this.
With those three little steps you can make almost every dependency replaceable. It is very save to do this, since you don’t need to implement anything by yourself. You just call the base constructor and create method signatures. If you have a clever IDE such as Visual Studio or / and are using productivity tools like the ReSharper most of this code will be generated and you barely type anything by hand.
Unfortunately there are some scenarios where this approach does not work and where more manual work is needed to create testable code. If the dependency class is sealed and you can’t derive from it, this solution does not work. In this case you might need to write a wrapper class around it, which might require some additional work and is therefore prone to bugs. The second scenario that I encountered is that some of the returned classed don’t had a public constructor. In that case there is not much you can do, to make this approach to work. At the moment I don’t have a solution for this scenario. If you found one, please let me know.
I did not come across more problems with this approach and I currently can’t imagine any more issues that might break this approach. I hope you can use this to make more of your code testable and create clean bug free software. Thank you for reading and see you next time.