模拟一个 CloudBlockBlob 并让它 return 成为一个流

Mocking a CloudBlockBlob and have it return a stream

我正在尝试对 Azure CloudBlockBlob 起订量并将其 return 和 Stream 以便我可以测试我的 BlobStorage 存储库是否正确处理输出.

但不知何故 returned 流总是空的。

单元测试代码:

//....

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));

//....

存储库代码:

//....

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;
}

//....

所以我的 returned MemoryStream ms 始终是一个空流,而不是我在 Moq Returns() 方法中使用的 stream 对象。

我怎样才能得到那个 blob return 我的样本流?

这是两个不同的流。获取在 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);
//....

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

注意

Copying begins at the current position in the current stream, and does not reset the position of the destination stream after the copy operation is complete.

所以在那种情况下,如果您打算从目标中读取,您可能想要重置它

//...

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

//...