An example of a testable Azure Table Storage

Testability and the means to abstract away your persistence layer in Windows Azure – two things that you don’t get for free. But you can get it really cheap, you just need some generics, interfaces. an IoC container and ~10 minutes.

While coding for this post I used StructureMap (can be downloaded from NuGet) and Windows Azure SDK 1.5. Should work just fine with an older version of the SDK though.

Really cheap

Wrapping up TableServiceContext

As you know you’ll need to extend TableServiceContext in order to save our entities in Azure Table Storage. Each and every example that I’ve seen is creating a specific ServiceContext for every entity type that needs to be saved. We’ll, I’m not going to do that.

We start with our interface.

public interface IServiceContext<TEntity> { IQueryable<TEntity> QueryableEntities { get; } void Create(TEntity entity); void Update(TEntity entity); void Delete(TEntity entity); }

Easy enough, right? A basic interface exposing CRUD capabilities. The implementation is not much harder.

public class ServiceContext<TEntity> : TableServiceContext, IServiceContext<TEntity> where TEntity : TableServiceEntity { private readonly string tableName; public ServiceContext() : base(AzureProvider.TableEndpoint, AzureProvider.Credentials) { tableName = typeof(TEntity).Name; } public IQueryable<TEntity> QueryableEntities { get { return CreateQuery<TEntity>(tableName); } } public void Create(TEntity entity) { AddObject(tableName, entity); SaveChanges(); } public void Update(TEntity entity) { UpdateObject(entity); SaveChanges(); } public void Delete(TEntity entity) { DeleteObject(entity); SaveChanges(); } }

So we create our own ServiceContext, extending TableServiceContext as well as implementing our very own IServiceContext<TEntity>. As you can see, in the base constructor, we use a static helper class AzureProvider which basically just exposes values from CloudStorageAccount. This is just for readability and really not necessary.

Also worth mentioning is that we use whatever type name TEntity has as the table name. So if we create a ServiceContext<Dog>, our table would be “Dog”. This makes life easier and also solves a nasty performance issue.

Due to a known performance issue with the ADO.NET Data Services client library, it is recommended that you use the table name for the class definition or define the ResolveType delegate on the DataServiceContext. If this is not used and when the entity class name is not the same as table name, query performance degrades with number of entities returned in the result.

WindowsClient.net

The ServiceContext class is basically the only code that will be untestable, but honestly… there are no actual logic or business rules inside that class. I would never strive for 100% coverage. As far as I’m concerned that’s a waste of time.

Now what?

First of all, in order to actually use our shiny new interface in a decent manner we need to register it with our IoC container of choice. As usual, I prefer StructureMap.

This little piece of code allows to instantiate a new class such as:

Our IoC container will be able to create it without any problems. This class will be completely ignorant what’s behind IServiceContext<TEntity>, it could just as well be a database. Since we inject all dependencies via the constructor this class is quite easy to test.

So?

Really, the point that I’m trying to make is that it’s not hard to wrap the not-very-testable parts of Windows Azure SDK. Just do it from start and you’ll be a happy (unit test writing) camper.

Happy testing!

Leave a Reply

Close Menu