Hi Everyone!

As you are aware I have decided to move away from MOQ and insted we will use FakeItEasy for mocking the Azure Storage SDK. This post is adoptation of this which is using Moq.

You can find the full series of how to perform unit and integration tests for Azure Blob Storage using Azurite Test Containers, and xUnit.

Getting started with testing for Azure Blob Storage : Dependency Injection

Getting started with testing for Azure Blob Storage : Unit Test with help of Moq

Getting started with testing for Azure Blob Storage : Unit Test with help of FakeItEasy (Alternative to MoQ)

Getting started with testing for Azure Blob Storage : Integration Test with help of TestContainers and Azurite

Getting started with testing for Azure Blob Storage : Mocking Azure Blob/File Storage SDK

This Post - Getting started with testing for Azure Blob Storage : Mocking Azure Blob/File Storage SDK Using FakeItEasy (Alternative to MoQ)

We will use the same code base we used in the previous post. So, if you have not read the previous post, I would recommend to read it first before proceeding further as we will skip the code part and focus on the testing part.

Writing Unit Tests

Finally, we have reached to the point where we can write unit tests for AzBlobService. Let’s write the unit tests for AzBlobService using FakeItEasy and xUnit. For this, I have created seperate class named AzBlobServiceTest which will contain all the unit tests for AzBlobService in our unit test project.

AzBlobServiceTest.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
public class AzBlobServiceTest
{
    private readonly StringWriter Output = new();
    private const string _connectionName = "testconnection";

    public AzBlobServiceTest()
    {
        Console.SetOut(Output);
    }

    [Fact]
    public async Task File_Upload_Suceess()
    {
        // Arrange
        var _azBlobServiceClientFactory = A.Fake<IAzureClientFactory<BlobServiceClient>>();
        var _azBlobServiceClient = A.Fake<BlobServiceClient>();
        var _azBlobContainerClient = A.Fake<BlobContainerClient>();
        var _azBlobClient = A.Fake<BlobClient>();
        var _azBlobSettingsOption = A.Fake<AzBlobSettingsOption>();

        var blobContainerInfo = BlobsModelFactory.BlobContainerInfo(default, default);
        var blobContentInfo = BlobsModelFactory.BlobContentInfo(default, default, default, default, default);

        A.CallTo(() => _azBlobContainerClient.CreateIfNotExistsAsync(default, default, default, default)).Returns(Response.FromValue(blobContainerInfo, default!));
        A.CallTo(() => _azBlobClient.UploadAsync(A.Dummy<Stream>(), default, default, default, default, default, default, default)).Returns(Response.FromValue(blobContentInfo, default!));
        A.CallTo(() => _azBlobContainerClient.GetBlobClient(default)).Returns(_azBlobClient);
        A.CallTo(() => _azBlobServiceClient.GetBlobContainerClient(default)).Returns(_azBlobContainerClient);
        A.CallTo(() => _azBlobServiceClientFactory.CreateClient(default)).Returns(_azBlobServiceClient);

        var _sut = new AzBlobService(_azBlobServiceClientFactory, _azBlobSettingsOption);

        // Act
        var result = await _sut.UploadFileToAzBlobAsync("samplefile.txt");

        // Assert
        Assert.True(result);
    }

    [Fact]
    public async Task File_Upload_Fail()
    {
       // Arrange
        var _azBlobServiceClientFactory = A.Fake<IAzureClientFactory<BlobServiceClient>>();
        var _azBlobServiceClient = A.Fake<BlobServiceClient>();
        var _azBlobContainerClient = A.Fake<BlobContainerClient>();
        var _azBlobClient = A.Fake<BlobClient>();
        var _azBlobSettingsOption = A.Fake<AzBlobSettingsOption>();


        var blobContainerInfo = BlobsModelFactory.BlobContainerInfo(default, default);
        var blobContentInfo = BlobsModelFactory.BlobContentInfo(default, default, default, default, default);

        A.CallTo(() => _azBlobContainerClient.CreateIfNotExistsAsync(default, default, default, default)).Returns(Response.FromValue(blobContainerInfo, default!));
        A.CallTo(() => _azBlobClient.UploadAsync(A.Dummy<Stream>(), default, default, default, default, default, default, default)).Returns(Response.FromValue(blobContentInfo, default!));
        A.CallTo(() => _azBlobContainerClient.GetBlobClient(default)).Returns(_azBlobClient);
        A.CallTo(() => _azBlobServiceClient.GetBlobContainerClient(default)).Returns(_azBlobContainerClient);
        A.CallTo(() => _azBlobServiceClientFactory.CreateClient(default)).Returns(_azBlobServiceClient);

        var _sut = new AzBlobService(_azBlobServiceClientFactory, _azBlobSettingsOption);

        // Act
        var result = await _sut.UploadFileToAzBlobAsync("");

        // Assert
        Assert.False(result);
        Assert.Contains("Unable to upload blob. Reason", Output.ToString());
    }
}
Nothing fancy here, we are just faking the dependency of BlobServiceClient and BlobContainerClient and injecting it to AzBlobService using AzBlobServiceClientFactory. Also we tried to fake all the required methods of BlobServiceClient and BlobContainerClient which are used in AzBlobService.

I have also created the scenario where file upload fails due to blank file name to show how to write negative unit tests.

Conclusion

In this article, we have learned how to write loosely coupled code for Azure Storage SDK and how to mock the Azure Storage SDK using FakeItEasy and xUnit. This whole series of articles was focused on Azure Blob Storage but you can use the same approach for Azure File Storage as well. For Azure File Storage, you just need to replace the BlobServiceClient with FileServiceClient and BlobContainerClient with ShareClient and BlobClient with ShareFileClient, and you are good to go. Also to mock the respose you will have FilesModelFactory instead of BlobsModelFactory.

You can find the source code here.