Saturday, 1 September 2018

Streaming mp3s from Azure blob storage gotcha

Have been wrestling with an issue one and off for a few weeks where have found mp3 files that previously played correctly in a web browser were having some issues relating to streaming. There's an example here. What I found - hopefully resolved now if you try the link - was that the audio would play, but the play bar that updates the position on the track wouldn't move, nor could the user navigate to parts of the audio to review it.

We're using jplayer and have the mp3 files hosted in Azure blob storage. All had worked fine for several years, but recently could see this issue on Chrome, even though they still played as expected in Edge. So must have been related to a relatively recent Chrome update.

The resolution though turned out to be a setting on the blob storage account, that I was led to via this Stackoverflow answer, that indicated setting the DefaultServiceVersion to an appropriate value might resolve it. And sure enough, when querying the current value I found it was null. Setting it to 2013-08-15 (and perhaps more recent versions) restored the play bar and streaming behaviour.

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).