模拟 CloudBlockBlob 并让它返回一个流

Rei*_*Wit 8 c# moq azure-storage asp.net-core

我正在尝试 Moq 一个 AzureCloudBlockBlob并让它返回一个,Stream以便我可以测试我的BlobStorage存储库是否正确处理输出。

但不知何故,返回的流总是空的。

单元测试代码:

//....

var stream = new MemoryStream();
var writer = new StreamWriter(stream);
writer.Write("sample data");
writer.Flush();
stream.Position = 0;

var blobMock = new Mock<CloudBlockBlob>(new Uri("http://tempuri.org/blob"));
blobMock
    .Setup(m => m.ExistsAsync())
    .ReturnsAsync(true);
blobMock
    .Setup(m => m.DownloadToStreamAsync(It.IsAny<MemoryStream>()))
    .Returns(Task.FromResult(stream));

//....
Run Code Online (Sandbox Code Playgroud)

存储库代码:

//....

var blob = GetContainer(container).GetBlockBlobReference(name);
if (await blob.ExistsAsync())
{
    var ms = new MemoryStream();
    await blob.DownloadToStreamAsync(ms);
    ms.Seek(0, SeekOrigin.Begin);
    return ms;
}

//....
Run Code Online (Sandbox Code Playgroud)

所以我返回MemoryStream ms的总是一个空流,而不是stream我在 MoqReturns()方法中使用的对象。

我怎样才能让那个 blob 返回我的样本流?

Nko*_*osi 10

这是两个不同的流。获取在 a 中的模拟参数中传递的流Callback并复制测试流。

例如

//....
var stream = new MemoryStream();
var writer = new StreamWriter(stream);
writer.Write("sample data");
writer.Flush();
stream.Position = 0;

var blobMock = new Mock<CloudBlockBlob>(new Uri("http://tempuri.org/blob"));
blobMock
    .Setup(m => m.ExistsAsync())
    .ReturnsAsync(true);
blobMock
    .Setup(m => m.DownloadToStreamAsync(It.IsAny<Stream>()))
    .Callback((Stream target) => stream.CopyTo(target)) //<---Something like this
    .Returns(Task.CompletedTask);
//....
Run Code Online (Sandbox Code Playgroud)

模拟实际上并不返回流。它假设作用于流,这就是为什么需要回调来复制预期行为的原因。

做记录

复制从当前流中的当前位置开始,复制操作完成后不会重置目标流的位置。

因此,在这种情况下,如果意图是从目标读取,您可能需要重置它

//...

.Callback((Stream target) => {
    stream.CopyTo(target);
    target.Position = 0;
})

//...
Run Code Online (Sandbox Code Playgroud)