Faking out Azure - Unit Testing with Microsoft Fakes
Overview
Microsoft Fakes provides an excellent framework for code isolation within Unit Tests and is only available for Visual Studio Enterprise subscriptions. Fakes do provide advantages over other frameworks (re., Moq and Rhino Mocks) as it allows for full code isolation and not just interfaces or public virtual members. There are alternatives to Fakes (e.g., Telerik JustMock and TypeMocks).
The MSDN project, Azure Storage and Microsoft Fakes, was created to show some of the cool things Microsoft Fakes provides when isolating Azure Storage.
Please see the project for more information and the following is shown here as an overview.
Sample
To illustrate a simple class, StorageManager, was created to send an update a product to an Azure Storage Table called Products. The entire class is shown below:
C#
Edit|Remove
namespace MSDNFakeOutStorage
{
public class StorageManager
{
public bool UpdateProducts(ProductEntity entity)
{
var table = GetClientForTable("Products");
var result = table.Execute(TableOperation.InsertOrReplace(entity));
return result.HttpStatusCode == 204;
}
private readonly string ConnectionString = ConfigurationManager.AppSettings["AzureStorageConnectionString"];
private CloudTable GetClientForTable(string tableName)
{
var account = CloudStorageAccount.Parse(ConnectionString);
var tableClient = account.CreateCloudTableClient();
var table = tableClient.GetTableReference(tableName);
table.CreateIfNotExists();
return table;
}
}
}
We will create two basic tests. One to test how the StorageManager behaves when the Products table is successfully updated and when it is not updated successfully.
To start we need to add to fakes to our project: Microsoft.WindowsAzure.Storage and System.Configuration:
https://code.msdn.microsoft.com/site/view/file/158055/1/ms1.jpg
The following shows the generated fakes in the project:
https://code.msdn.microsoft.com/site/view/file/158056/1/ms2.jpg
Unit Test - System.Configuration
The first step is to isolate the ConfigurationManager.AppSettings from the StorageManager.ConnectionString. The following will divert all ConfigurationManager.AppSettings[] calls to a new NameValueCollection and is shown below:
C#
Edit|Remove
ShimConfigurationManager.AppSettingsGet = () =>
{
var settings = new NameValueCollection();
settings.Add("AzureStorageConnectionString", "valueOfAzureStorageConnectionString");
return settings;
};
When debugging the unit test you can see the magic working:
https://code.msdn.microsoft.com/site/view/file/158057/1/ms3.jpg
Unit Test - Microsoft.WindowsAzure.Storage
The next step is to create a shim for the Azure Storage components used in the project. A shim was used instead of a stub as we are not replacing the entire object but only diverting messages to our test functionality.
In the code snippet below, note how all calls from the StorageManager class to the underlying storage classes are supplied:
C#
Edit|Remove
ShimCloudStorageAccount.ParseString = (connectionString) =>
{
if (connectionString != "valueOfAzureStorageConnectionString")
Assert.Fail(string.Format($"Unexpected connection string value of {connectionString} received!"));
return new ShimCloudStorageAccount
{
CreateCloudTableClient = () => new ShimCloudTableClient
{
GetTableReferenceString = (tableName) =>
{
if (tableName != "myTable")
Assert.Fail("The table name should be Products");
return new ShimCloudTable
{
CreateIfNotExistsTableRequestOptionsOperationContext = (requestOptions, operationContext) => true,
ExecuteTableOperationTableRequestOptionsOperationContext = (operation, requestOptions, context) =>
{
return new TableResult
{
// successful response code is No Content
// https://msdn.microsoft.com/en-us/library/azure/hh452242.aspx
HttpStatusCode = 204
};
}
};
}
}
};
};
Summary
This article provides an example of how Microsoft Fakes can isolate Azure Storage from code. Microsoft Fakes empowers some developers to write complete unit tests and for others helps to reduce the credibility of using the "It's too hard" excuse in avoiding to write unit tests.