简体   繁体   中英

Mock of IBinder fails when unit testing Activity Function

I am trying to test an activity function which has the following definition:

[FunctionName(nameof(LoadReferenceFromBlobStorage))]
public static async Task<string> Run([ActivityTrigger] string blobName,
    IBinder binder,
    ILogger log)
{
    StorageAccountAttribute storageAccountAtt = new StorageAccountAttribute("AzureWebJobsStorage");
    CloudStorageAccount storageAccount = await binder.BindAsync<CloudStorageAccount>(storageAccountAtt, CancellationToken.None);
    CloudBlobClient client = storageAccount.CreateCloudBlobClient();

    //...
}

I mock the IBinder in the unit test as:

[TestMethod]
public async Task GetReference()
{
    var attribute = new StorageAccountAttribute("UseDevelopmentStorage=true;");
    var mock = new Mock<IBinder>();
    CloudStorageAccount mockedResult = null;
    CloudStorageAccount.TryParse("UseDevelopmentStorage=true;", out mockedResult);
    mock.Setup(x => x.BindAsync<CloudStorageAccount>(attribute, CancellationToken.None))
            .ReturnsAsync(mockedResult);

    ILogger logger = NullLoggerFactory.Instance.CreateLogger("log");
    var res = await LoadReferenceFromBlobStorage.Run("name", mock.Object, logger);

    //...
}

The test calls the activity successfully but the result of binder.BindAsync is always null .

Am I missing something?

You are comparing two separate instances in the setup and what is actually invoked in the test.

The method under test is creating its own instance of StorageAccountAttribute with a hard-coded "AzureWebJobsStorage" , while the test is using another instance for the setup expression. Those will not match when exercising the test and thus the mock will return null as experienced.

Try to loosen the setup by using It.IsAny<T>() is the expectation expression.

//Arrange    
CloudStorageAccount mockedResult = null;
CloudStorageAccount.TryParse("UseDevelopmentStorage=true;", out mockedResult);

var mock = new Mock<IBinder>();
mock
    .Setup(x => x.BindAsync<CloudStorageAccount>(It.IsAny<StorageAccountAttribute>(), CancellationToken.None))
    .ReturnsAsync(mockedResult);

ILogger logger = Mock.Of<ILogger>();
//Act
var res = await LoadReferenceFromBlobStorage.Run("name", mock.Object, logger);

//Assert

//...

That will allow

 CloudStorageAccount storageAccount = await binder.BindAsync<CloudStorageAccount>(storageAccountAtt, CancellationToken.None);

to behave as expected when invoked.

Concerning the StorageAccountAttribute hard-coded argument you may want to also consider refactoring that so it can be replaced when testing so as not to have issues with the storage being used when testing.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM