如何为使用流作为参数的方法编写unitTest



我有类ImportProvider,我想为Import方法编写单元测试。

但这应该是单元测试,所以我不想从文件到流进行读取。知道吗?

public class ImportProvider : IImportProvider
{ 
public bool Import(Stream stream)
{
//Do import
return isImported;
}
}
public interface IImportProvider
{
bool Import(Stream input);
}

这是单元测试:

[TestMethod]
public void ImportProvider_Test()
{
// Arrange           
var importRepository = new Mock<IImportRepository>(); 
var imp = new ImportProvider(importRepository.Object);
//Do setup...
// Act
var test_Stream = ?????????????
// This working but not option:
//test_Stream = File.Open("C:/ExcelFile.xls", FileMode.Open, FileAccess.Read);
var result = imp.Import(test_Stream);
// Assert    
Assert.IsTrue(result);
}

使用MemoryStream。不确定您的函数期望得到什么,但可以在其中插入UTF-8字符串,例如:

//Act
using (var test_Stream = new MemoryStream(Encoding.UTF8.GetBytes("whatever")))
{
var result = imp.Import(test_Stream);
// Assert    
Assert.IsTrue(result);
}

编辑:如果你需要一个Excel文件,而你无法从磁盘上读取文件,你能在测试项目中添加一个Excel作为嵌入资源吗?请参阅如何使用Visual C#嵌入和访问资源

然后你可以像这样的流读取:

//Act
using (var test_Stream = this.GetType().Assembly.GetManifestResourceStream("excelFileResource"))
{
var result = imp.Import(test_Stream);
// Assert    
Assert.IsTrue(result);
}

您可以使用MemoryStream为测试提供纯内存流。

我的解决方案是将Stream封装在您自己的类中,让我们将其命名为实现接口IStreamStreamWrapper。现在将导入签名更改为

public bool Import(IStream stream)

现在您可以模拟该流,如果您想在生产代码中使用它,您应该传递StreamWrapper,否则就是mock。

如果您是接受网络流、http流、AWS S3流和其他"不可查找";流,那么使用MemoryStream不是你的最佳想法,因为它是";"可查找";。

也就是说,它太好了,太温和了,可以进行各种操作。

为了对抗与这些";粗糙的";流,接近真实情况,我建议从MemoryStream继承,然后覆盖.CanSeek(false).Length(throw NotSupported).Positionsetter(throw nonsupported)等。

现实生活中的例子:我正在使用一个图像处理库,该库接受Stream作为输入。我的测试运行良好,因为它们是基于MemoryStreams和FileStreams的。但是,一旦我将代码部署到生产中,在那里我处理来自AmazonS3的图像,我就会遇到各种异常,因为图像库期望有一个可查找的流。

这是我使用的代码:

public class BadBoyStream : MemoryStream
{
public NonSeekableStream(byte[] buffer) : base(buffer) { }
public override bool CanSeek => false;
public override long Length => throw new NotSupportedException();
public override long Position
{
get => base.Position;
set => throw new NotSupportedException();
}
public override long Seek(long offset, SeekOrigin origin) => throw new NotImplementedException();
public override void SetLength(long value) => throw new NotSupportedException();
}

使用像JustLock、TypeMock或Microsoft Fakes这样的隔离框架,您将能够模拟流。

坏消息是,据我所知,他们都得到了报酬。

相关内容

  • 没有找到相关文章