How to mock Azure blobContainerClient.GetBlobsAsync()
Asked Answered
E

1

6

I have a Azure blob container which I am accessing using below code -

       var blobContainerClient = GetBlobContainer(containerName);
            if (blobContainerClient != null)
            {
                // List all blobs in the container
                await foreach (BlobItem blobItem in blobContainerClient.GetBlobsAsync())
                {
                    queuedBlobsList.Add(new QueuedBlobs { BlobName = blobItem.Name, LastModified = blobItem.Properties.LastModified });
                }
            }

    private BlobContainerClient GetBlobContainer(string containerName)
    {
        return gen2StorageClient != null
            ? gen2StorageClient.GetBlobContainerClient(containerName)
            : gen1StorageClient.GetBlobContainerClient(containerName);
    }

The clients are initialised in constructor - public class BlobService : IBlobService {
private readonly BlobServiceClient gen1StorageClient, gen2StorageClient;

   public BlobService(BlobServiceClient defaultClient, IAzureClientFactory<BlobServiceClient> clientFactory)
        {
              gen1StorageClient = defaultClient;
              if (clientFactory != null)
              {
               gen2StorageClient = clientFactory.CreateClient("StorageConnectionString");
              }
       }
    }

And my unit test where I am setting GetBlobsAsync is like this - But I want to add list of BlobItems to test another loop.

    private static Mock<BlobContainerClient> GetBlobContainerClientMockWithListOfBlobs()
    {
        var blobContainerClientMock = new Mock<BlobContainerClient>("UseDevelopmentStorage=true", EnvironmentConstants.ParallelUploadContainer);
        var cancellationToken = new CancellationToken();
        var blobs = new List<BlobItem>();

        //AsyncPageable<BlobItem> blobItems = new AsyncPageable<BlobItem>(); -- Not allowing
        blobContainerClientMock.Setup(x => x.GetBlobsAsync(BlobTraits.All, BlobStates.All, null, cancellationToken)).Returns(It.IsAny<AsyncPageable<BlobItem>>());
        return blobContainerClientMock;
    }
Emoryemote answered 6/6, 2022 at 13:10 Comment(0)
P
7

I came to this question because I also had the same issue.

Based on this article

AsyncPageable<T> and Pageable<T> are classes that represent collections of models returned by the service in pages.

The method GetBlobsAsync returns an AsyncPageable.

To Create an AsyncPageable you need first to create a BlobItem Page.

To create a Page<T> instance, use the Page<T>.FromValues method, passing a list of items, a continuation token, and the Response.

So let's start creating the list of items:

var blobList = new BlobItem[]
{
    BlobsModelFactory.BlobItem("Blob1"),
    BlobsModelFactory.BlobItem("Blob2"),
    BlobsModelFactory.BlobItem("Blob3")
};

Note: BlobItem has an internal constructor but I found in this answer that there's a BlobsModelFactory.

After having the list of blobs is time to create a Page<BlobItem>:

Page<BlobItem> page = Page<BlobItem>.FromValues(blobList, null, Mock.Of<Response>());

And finally, create the AsyncPageable<BlobItem>

AsyncPageable<BlobItem> pageableBlobList = AsyncPageable<BlobItem>.FromPages(new[] { page });

And now you are able to use this to mock GetBlobsAsync method:

blobContainerClientMock
    .Setup(m => m.GetBlobsAsync(
        It.IsAny<BlobTraits>(),
        It.IsAny<BlobStates>(),
        It.IsAny<string>(),
        It.IsAny<CancellationToken>()))
    .Returns(pageableBlobList);

I hope this helps others with this issue.

André

Pforzheim answered 15/12, 2022 at 13:58 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.