In Making a Mockery of Extension Methods - way back in 2014 - I wrote about a technique for a code workaround that would facilitate replacing extension methods (global static methods) with mock objects for unit testing. Over the years I've used this technique a few times and found two major problems:
- The technique of static delegate substitution is simply strange and requires too much thinking / analysis for good maintenance.
- The unit tests are brittle, often failing on the first try due to multiple tests interacting with each other as they replace the static delegate.
Interestingly, I've found the second to be true with both XUnit and NUnit, even when supposedly running tests serially. This problem did not occur as frequently when I first started using the technique five years ago; I was using VS Tests or NUnit 2 back then, so perhaps the more recent brittleness is from the change in frameworks.
At last I grew tired of the technique and decided it would be better to simply replace it with something more familiar: an injectable class. Thus the recipe:
- For a large set of extension methods over unmockable code - for example extension methods around database interaction - best to go ahead and create a thin adapter layer with an interface and constructor injection.
- For a small static method over unmockable code, consider a small class with optional interface for either constructor or property injection.
- If tempted to introduce a global static for any reason, consider instead using of these two techniques.