如何正确Mock BlobBaseClient.DownloadTo(Stream)方法?
问题解决方法
核心问题分析
你当前的代码存在两个关键问题:
- Mock的
MemoryStream未写入任何内容,读取自然为空 - 误解了
DownloadTo方法的工作逻辑——该方法的核心是将内容写入传入的流参数,而非依赖返回的Response对象的ContentStream(除非你的业务逻辑特殊定义)
修正方案一(推荐:使用真实流,贴近真实场景)
直接在DownloadTo的Setup中拦截传入的流,写入目标内容:
var xmlContent = @"<?xml version='1.0'?>test data</xml>"; var responseMock = new Mock<Response>(); // 按需设置Response的Content属性 responseMock.Setup(r => r.Content).Returns(new BinaryData(xmlContent)); // 关键:Setup DownloadTo时,向传入的流写入内容并重置位置 _blobClientMock.Setup(b => b.DownloadTo(It.IsAny<MemoryStream>())) .Callback<MemoryStream>(targetStream => { var contentBytes = Encoding.UTF8.GetBytes(xmlContent); targetStream.Write(contentBytes, 0, contentBytes.Length); // 重置流位置到开头,确保后续读取能获取内容 targetStream.Position = 0; }) .Returns(responseMock.Object);
修正方案二(若必须Mock Stream)
如果业务场景要求必须MockMemoryStream,需要为Mock对象设置读取逻辑和位置属性:
var xmlContent = @"<?xml version='1.0'?>test data</xml>"; var contentBytes = Encoding.UTF8.GetBytes(xmlContent); var streamMock = new Mock<MemoryStream>(); // 设置Mock Stream的Read行为,模拟内容读取 streamMock.Setup(s => s.Read(It.IsAny<byte[]>(), It.IsAny<int>(), It.IsAny<int>())) .Callback<byte[], int, int>((buffer, offset, count) => { var bytesToCopy = Math.Min(count, contentBytes.Length - (int)streamMock.Object.Position); Array.Copy(contentBytes, (int)streamMock.Object.Position, buffer, offset, bytesToCopy); streamMock.Object.Position += bytesToCopy; }) .Returns<int, int, int>((buffer, offset, count) => { return Math.Min(count, contentBytes.Length - (int)streamMock.Object.Position); }); // 设置Position属性的可读写 streamMock.SetupProperty(s => s.Position, 0); var responseMock = new Mock<Response>(); responseMock.Setup(r => r.Content).Returns(new BinaryData(xmlContent)); responseMock.Setup(r => r.ContentStream).Returns(streamMock.Object); _blobClientMock.Setup(b => b.DownloadTo(It.IsAny<MemoryStream>())).Returns(responseMock.Object);
注意事项
- 调用
DownloadTo后,若要读取传入的流,必须确保流的Position重置为0,否则读取指针会停在流的末尾 - 测试时优先使用真实的
MemoryStream,Mock流仅用于特殊场景,避免不必要的复杂度
内容的提问来源于stack exchange,提问作者Miro Georgiev
相关产品推荐
相关产品推荐

