如何从集成测试将文件上传到端点

Sam*_*amo 3 c# asp.net-mvc integration-testing file-upload moq

当客户端上传文件时,可以在 中找到该文件this.Request.Files,其类型为HttpFileCollectionBase

HttpFileCollectionBase包含HttpPostedFileBase条目。

这些对象的属性是只读的,所以我希望我可以设置一些模拟。我的模拟请求将返回一个模拟HttpFileCollection,并且该集合将包含一个模拟HttpPostedFile。该对象的属性InputStream将返回一个FileStream对象,我将使用源代码管理中的真实文件实例化该对象。

  1. 这是从集成测试将文件上传到端点的好方法吗?
  2. 如果这是一个好方法,我该如何模拟它Moq
  3. 如果这不是一个好方法,您能建议更好的方法吗?

谢谢!

Ale*_*eck 5

我对 ASP.NET MVC 一无所知,但看起来您需要执行类似的操作来设置模拟依赖项:

MemoryStream stream = new MemoryStream();

var mockFile = new Mock<HttpPostedFileBase>();
var mockFiles = new Mock<HttpFileCollectionBase>();
var mockRequest = new Mock<HttpRequestBase>();

mockFile.Setup(f => f.InputStream).Returns(stream);

// if for example, you index the file by name.
mockFiles.Setup(f => f[It.IsAny<string>()]).Returns(mockFile.Object);

mockRequest.Setup(r => r.Files).Returns(() => mockFiles.Object);

// write expected data to your memory stream, then instantiate your class 
// under test using the mockRequest.Object
Run Code Online (Sandbox Code Playgroud)

在单元测试中,我会使用内存流而不是文件,但文件流的工作原理是相同的。

如果您想避免模拟和设置所有这些依赖项,您可以将它们放在UploadedFiles抽象后面,使您的代码依赖于抽象,并且仅模拟UploadedFiles。这仅需要一个薄包装即可Request.Files按名称(或您访问它们的方式)获取文件流。这更好,因为下游代码现在依赖于UploadedFiles, Streamand string,而不是HttpRequestBase, HttpFileCollectionBase, HttpPostedFileBase, Streamand string

然后设置将被简化为如下所示:

MemoryStream stream = new MemoryStream();
var mockUploadedFiles = new Mock<UploadedFiles>();
mockUploadedFiles.Setup(u => u.GetFile(It.IsAny<string>())).Returns(stream);
Run Code Online (Sandbox Code Playgroud)