I am writing unit tests for my code and have come across a method, which throws a StorageException when trying to Create a queue and AddMessage to the queue. I would like to test if the exception handling works fine. In order to do that I had an idea of using a mock for the CloudQueue, but later found out this class is sealed. Is there any way to test the exception handling (or force a StorageException) without actually changing the production code?
The easiest way to handle this is with an Interface around a CloudQueueClient
(which is what @tyrion) suggested, above .. but also an interface for a ICloudQueue
public interface ICloudQueueClientWrapper
{
ICloudQueueWrapper GetQueueReference(string queueName);
}
// ----------------
public class CloudQueueClientWrapper : ICloudQueueClientWrapper
{
private readonly Lazy<CloudQueueClient> _cloudQueueClient;
public CloudQueueClientWrapper(string connectionStringName)
{
connectionStringName.ShouldNotBeNullOrWhiteSpace();
_cloudQueueClient = new Lazy<CloudQueueClient>(() =>
{
// We first need to connect to our Azure storage.
var storageConnectionString = CloudConfigurationManager.GetSetting(connectionStringName);
var storageAccount = CloudStorageAccount.Parse(storageConnectionString);
// Create the queue client.
return storageAccount.CreateCloudQueueClient();
});
}
public ICloudQueueWrapper GetQueueReference(string queueName)
{
queueName.ShouldNotBeNullOrWhiteSpace();
var cloudQueue = _cloudQueueClient.Value.GetQueueReference(queueName);
return new CloudQueueWrapper(cloudQueue);
}
// Add more methods here which are a one-to-one match against the underlying CQC.
}
So that's the first interface and wrapper ... and notice this returns an ICloudQueue
instance .. so lets do that now...
public interface ICloudQueueWrapper
{
Task AddMessageAsync(CloudQueueMessage message);
}
public class CloudQueueWrapper : ICloudQueueWrapper
{
private readonly CloudQueue _cloudQueue;
public CloudQueueWrapper(CloudQueue cloudQueue)
{
cloudQueue.ShouldNotBeNull();
_cloudQueue = cloudQueue;
}
public async Task AddMessageAsync(CloudQueueMessage message)
{
message.ShouldNotBeNull();
await _cloudQueue.AddMessageAsync(message);
}
}
Ok ... so now lets try using this in some unit test :)
[Theory]
[MemberData(nameof(StockIds))]
public async Task GivenSomeData_DoFooAsync_AddsDataToTheQueue(string[] stockIds)
{
// Arrange.
var cloudQueue = Mock.Of<ICloudQueueWrapper>();
var cloudQueueClient = Mock.Of<ICloudQueueClientWrapper>();
Mock.Get(cloudQueueClient).Setup(x => x.GetQueueReference(It.IsAny<string>()))
.Returns(cloudQueue);
var someService = new SomeService(cloudQueueClient);
// Act.
await someService.DoFooAsync(Session);
// Assert.
// Did we end up getting a reference to the queue?
Mock.Get(cloudQueueClient).Verify(x => x.GetQueueReference(It.IsAny<string>()), Times.Once);
// Did we end up adding something to the queue?
Mock.Get(cloudQueue).Verify(x => x.AddMessageAsync(It.IsAny<CloudQueueMessage>()), Times.Exactly(stockids.Length));
}
We have used the Microsoft Fakes framework to be able to unit test similar Azure SDK classes in the past. There is a little learning curve up front, but it works great.
https://msdn.microsoft.com/en-us/library/hh549175.aspx
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With