【发布时间】:2015-07-02 15:42:06
【问题描述】:
我正在尝试为使用 HttpContext.Current.Request.Files 的 Web API 方法编写测试,经过详尽的搜索和实验后,我无法弄清楚如何模拟它。正在测试的方法如下所示:
[HttpPost]
public HttpResponseMessage Post()
{
var requestFiles = HttpContext.Current.Request.Files;
var file = requestFiles.Get(0);
//do some other stuff...
}
我知道有other questionssimilar to this,但他们没有解决这个具体情况。
如果我尝试模拟上下文,我会遇到Http* 对象层次结构的问题。假设我像这样设置了各种模拟对象(使用Moq):
var mockFiles = new Mock<HttpFileCollectionBase>();
mockFiles.Setup(s => s.Count).Returns(1);
var mockFile = new Mock<HttpPostedFileBase>();
mockFile.Setup(s => s.InputStream).Returns(new MemoryStream());
mockFiles.Setup(s => s.Get(It.IsAny<int>())).Returns(mockFile.Object);
var mockRequest = new Mock<HttpRequestBase>();
mockRequest.Setup(s => s.Files).Returns(mockFiles.Object);
var mockContext = new Mock<HttpContextBase>();
mockContext.Setup(s => s.Request).Returns(mockRequest.Object);
正在尝试将其分配给当前上下文...
HttpContext.Current = mockContext.Object;
...导致编译器错误/红线,因为它Cannot convert source type 'System.Web.HttpContextBase' to target type 'System.Web.HttpContext'。
我还尝试深入研究构造的控制器对象附带的各种上下文对象,但找不到 a) 是控制器方法主体中 HttpContext.Current 调用的返回对象和 b) 提供对标准HttpRequest 属性,如Files。
var requestMsg = controller.Request; //returns HttpRequestMessage
var context = controller.ControllerContext; //returns HttpControllerContext
var requestContext = controller.RequestContext; //read-only returns HttpRequestContext
还需要注意的是,我根本无法更改我正在测试的控制器,因此我无法更改构造函数以允许注入上下文。
有什么方法可以模拟 HttpContext.Current.Request.Files 以在 Web API 中进行单元测试?
更新
虽然我不确定这是否会被团队接受,但我正在尝试将 Post 方法更改为使用Request.Content,正如Martin Liversage 所建议的那样。它目前看起来像这样:
public async Task<HttpResponseMessage> Post()
{
var uploadFileStream = new MultipartFormDataStreamProvider(@"C:\temp");
await Request.Content.ReadAsMultipartAsync(uploadFileStream);
//do the stuff to get the file
return ActionContext.Request.CreateResponse(HttpStatusCode.OK, "it worked!");
}
我的测试看起来像这样:
var byteContent = new byte[]{};
var content = new MultipartContent { new ByteArrayContent(byteContent) };
content.Headers.Add("Content-Disposition", "form-data");
var controllerContext = new HttpControllerContext
{
Request = new HttpRequestMessage
{
Content = new MultipartContent { new ByteArrayContent(byteContent) }
}
};
现在我在ReadAsMultipartAsync 上遇到错误:
System.IO.IOException: Error writing MIME multipart body part to output stream. ---> System.InvalidOperationException: The stream provider of type 'MultipartFormDataStreamProvider' threw an exception. ---> System.InvalidOperationException: Did not find required 'Content-Disposition' header field in MIME multipart body part.
【问题讨论】:
-
顺便说一句,如果你真的不能改变你的代码来移除对
HttpContext.Current依赖的直接耦合,那么this via reflection有很长的路要走
标签: c# unit-testing asp.net-web-api moq httpcontext