Skip to main content

Refactoring an interface to facilitate unit testing

Short post to follow, generalising something I've just done in an active project that seems to have general relevance. I had an interface and class like this, that wasn't easy to put under a unit test.

interface ISomething
{
    string GetValue();  
    string GetComplicatedConvertedValue();
}

class MySomething : ISomething
{
    string GetValue()
    {
        // Get value from something that's a simple one-liner call but not easy to mock or stub (in my case, Sitecore settings)
        ...
    }
    
    string GetComplicatedConvertedValue()
    {
        var rawValue = GetValue();
        
        // Do some processing on the raw value that ideally we'd like under unit test, and return it
        ...
    }
}

One answer I realised is that, as the main value for testing this class is in the second method - retrieving the raw value is hard to test, but little value as it's a one liner into platform functionality - I can just remove that from the interface, and instead implement it as a testable extension method.

interface ISomething
{
    string GetValue();
}

class MySomething : ISomething
{
    string GetValue()
    {
        // Get value from something that's a simple one-liner call but not easy to mock or stub (in my case, Sitecore settings)
        ...
    }
}

static class SomethingExtensions
{
    static string GetComplicatedConvertedValue(this ISomething something)
    {
        var rawValue = something.GetValue();
        
        // Do some processing on the raw value that ideally we'd like under unit test, and return it
        ...
    }
}

Then it's quite easy to write a test on the extension method, using a mocked or stubbed implementation of ISomething. Fairly obvious in hindsight - or maybe foresight you might be thinking! - but nonetheless seems something that might be easy to do (i.e. make an interface too wide, and thus make some code hard to test in the implementation of that interface).

Comments