使用NSubstitute模拟BlobClient.DownloadToAsync时流为空的问题排查
BlobClient.DownloadToAsync 模拟失败(流为空)的解决办法
核心问题分析
你当前的测试代码存在两个关键错误:
- 写入内容后的内存流未重置
Position到起始位置,导致后续读取时直接从流的末尾开始,自然读不到数据 - 错误使用
BlobDownloadStreamingResult模拟DownloadToAsync的返回值——实际上DownloadToAsync的作用是将Blob内容写入你传入的Stream,而非返回包含流的响应对象
修正后的测试用例代码
针对你需要的三个场景,给出正确的模拟方式(基于NSubstitute):
场景1:空文件下载
// 模拟空文件:无需向传入的Stream写入任何内容 blobClient.DownloadToAsync(Arg.Any<Stream>()).Returns(Task.CompletedTask);
场景2:仅含CSV表头的文件下载
var headerContent = "Header1,Header2,Header3\n"; using var headerStream = new MemoryStream(Encoding.UTF8.GetBytes(headerContent)); // 当调用DownloadToAsync时,将测试流的内容复制到传入的Stream中 blobClient.DownloadToAsync(Arg.Do<Stream>(targetStream => { headerStream.Position = 0; headerStream.CopyTo(targetStream); })).Returns(Task.CompletedTask);
场景3:含CSV表头及一行数据的文件下载
var fullContent = "Header1,Header2,Header3\nData1,Data2,Data3\n"; using var fullStream = new MemoryStream(Encoding.UTF8.GetBytes(fullContent)); blobClient.DownloadToAsync(Arg.Do<Stream>(targetStream => { fullStream.Position = 0; fullStream.CopyTo(targetStream); })).Returns(Task.CompletedTask);
额外注意事项
- 你的业务代码中,在调用
DownloadToAsync后已经将fileStream.Position重置为0,这部分是正确的,无需修改 - 用
Encoding.UTF8.GetBytes直接创建内存流,比StreamWriter更简洁,也能避免忘记Flush或重置位置的问题
内容的提问来源于stack exchange,提问作者LockTar
相关产品推荐
相关产品推荐

