System.ArgumentException:无效的回调。在返回类型为“Task<Response>”的方法上设置无法调用返回类型为“Task”的回调

System.ArgumentException : Invalid callback. Setup on method with return type 'Task<Response>' cannot invoke callback with return type 'Task'

提问人:Faouzeya 提问时间:11/9/2023 更新时间:11/9/2023 访问量:56

问:

我想为我的方法实现一个名为 GetFileContentAsync 的单元测试,该方法从 Azure 存储获取文件内容。

这是我的班级:

using Azure.Storage.Blobs;
using Azure.Storage.Blobs.Models;
using Azure.Storage.Sas;
using Microsoft.Extensions.Options;

public class StorageService : IStorageService
{
 private const string DefaultContentType = "application/octet-stream";

private readonly BlobServiceClient _blobServiceClient;
private readonly StorageOptions _options;

public StorageService(BlobServiceClient blobServiceClient, IOptions<StorageOptions> storageOptions)
{
    _blobServiceClient = blobServiceClient;
    _options = storageOptions.Value;
}

public async Task<(byte[] Content, string ContentType)> GetFileContentAsync(string containerName, string filenamePath)
{
    using var memoryStream = new MemoryStream();

    var contentType = "application/octet-stream";

BlobContainerClient containerClient = _blobServiceClient.GetBlobContainerClient(containerName);
bool exists = await containerClient.ExistsAsync();

    if (exists)
    {
        await foreach (var blobItem in containerClient.GetBlobsAsync(prefix: filenamePath))
        {
            var blobClient = containerClient.GetBlobClient(blobItem.Name);

            contentType = blobItem.Properties.ContentType;

            await blobClient.DownloadToAsync(memoryStream);
        }
    }

    return (memoryStream.ToArray(), contentType);
}
}

这是我实现的单元测试:

    [Fact]
    public async Task GetFileContentAsync_ReturnContent()
    {
        // Arrange
        var mockBlobServiceClient = new Mock<BlobServiceClient>();
        var mockBlobContainerClient = new Mock<BlobContainerClient>();
        var mockBlobClient = new Mock<BlobClient>();
        var options = Options.Create(new StorageOptions());

        var containerName = "test-container";
        var filenamePath = "file/path/test.txt";

        var expectedContentType = "text/plain"; // Content type to return
        var expectedContent = Encoding.UTF8.GetBytes("test content");

        var blobItems = new[]
        {
            BlobsModelFactory.BlobItem(filenamePath)
        };

        Page<BlobItem> page = Page<BlobItem>.FromValues(blobItems, null, Mock.Of<Response>());
        AsyncPageable<BlobItem> pageableBlobList = AsyncPageable<BlobItem>.FromPages(new[] { page });

        mockBlobServiceClient
            .Setup(x => x.GetBlobContainerClient(It.IsAny<string>()))
            .Returns(mockBlobContainerClient.Object);

        mockBlobContainerClient
            .Setup(client => client.ExistsAsync(CancellationToken.None))
            .ReturnsAsync(Response.FromValue(true, new Mock<Response>().Object));

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

        mockBlobContainerClient.Setup(x => x.GetBlobClient(It.IsAny<string>()))
            .Returns(mockBlobClient.Object);

        var memoryStream = new MemoryStream(expectedContent);

        mockBlobClient
        .Setup(x => x.DownloadToAsync(It.IsAny<Stream>(), CancellationToken.None))
        .Returns((Stream stm, CancellationToken token) => memoryStream.CopyToAsync(stm, token));

        var storageService = new StorageService(mockBlobServiceClient.Object, Options.Create(new StorageOptions()));

        // Act
        var (content, contentType) = await storageService.GetFileContentAsync(containerName, filenamePath);

        // Assert
        Assert.Equal(expectedContent, content);
        Assert.Equal(expectedContentType, contentType);
    }

因此,当我运行此测试时,我收到与以下代码行相关的错误:System.ArgumentException : Invalid callback. Setup on method with return type 'Task<Response>' cannot invoke callback with return type 'Task'.

  mockBlobClient
        .Setup(x => x.DownloadToAsync(It.IsAny<Stream>(), CancellationToken.None))
        .Returns((Stream stm, CancellationToken token) => memoryStream.CopyToAsync(stm, token));

谁能帮我正确地模拟这个方法DownloadToAsync?

C# .NET Azure 单元测试 最小起订量

评论

0赞 Mark Seemann 11/10/2023
该错误似乎说返回一个 ,但为了设置 的返回值,您必须提供一个 .换言之,表达式不进行类型检查。CopyToAsyncTaskDownloadToAsyncTask<Response>Returns

答: 暂无答案