Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there any way to mock Azure CloudQueueClient or CloudQueue?

Tags:

c#

.net

moq

azure

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?

like image 824
SalysBruoga Avatar asked Jul 21 '16 09:07

SalysBruoga


2 Answers

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));
    }
like image 77
Pure.Krome Avatar answered Sep 20 '22 20:09

Pure.Krome


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

like image 42
Justin Patten Avatar answered Sep 21 '22 20:09

Justin Patten