简体   繁体   English

单元测试活动功能时,IBinder模拟失败

[英]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: 我在单元测试中将IBinder模拟为:

[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 . 该测试成功调用了活动,但binder.BindAsync的结果始终为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. 被测试的方法正在创建带有硬编码"AzureWebJobsStorage"自己的StorageAccountAttribute实例,而测试则将另一个实例用于设置表达式。 Those will not match when exercising the test and thus the mock will return null as experienced. 进行测试时,这些将不匹配,因此模拟将根据经验返回null

Try to loosen the setup by using It.IsAny<T>() is the expectation expression. 尝试使用It.IsAny<T>()来放松设置It.IsAny<T>()是期望表达式。

//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. 关于StorageAccountAttribute硬编码的参数,您可能还需要考虑重构,以便在测试时可以将其替换,以免测试时使用的存储出现问题。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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