测试使用HttpContext.Current.Request.Files一个Web API的方法? [英] Testing a Web API method that uses HttpContext.Current.Request.Files?

查看:5495
本文介绍了测试使用HttpContext.Current.Request.Files一个Web API的方法?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图写一个测试为使用Web API方法 HttpContext.Current.Request.Files 之后详尽的搜索和实验我无法弄清楚如何嘲笑为了它。被测试的方法是这样的:

I am attempting to write a test for a Web API method that uses HttpContext.Current.Request.Files and after exhaustive searching and experimentation I cannot figure out how to mock for it. The method being tested looks like this:

[HttpPost]
public HttpResponseMessage Post()
{
    var requestFiles = HttpContext.Current.Request.Files;
    var file = requestFiles.Get(0);
    //do some other stuff...
}

我认识到,有其他问题类似于此的,但是它们没有解决这一具体情况。

I realize that there are other questions similar to this, but they do not address this specific situation.

如果我试图嘲弄的背景下,我碰上的的Http * 对象层次的问题。说我设置各种模仿对象(使用起订量)是这样的:

If I attempt to mock the context, I run into issues with the Http* object hierarchy. Say I set up various mock objects (using Moq) like this:

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);

试图将其分配给当前上下文...

Attempting to assign it to the current context...

HttpContext.Current = mockContext.Object;

...导致一个编译器错误/红线,因为它无法将源类型System.Web.HttpContextBase为目标类型'System.Web.HttpContext

我也试图钻进来与构造控制对象的各种上下文中的对象,但无法找到一个a)是一个返回的对象 HttpContext.Current 在控制器方法体调用和b)提供访问标准的Htt prequest 属性,例如文件

I have also tried drilling into various context objects that come with the constructed controller object, but can't find one that a) is the return object of an HttpContext.Current call in the controller method body and b) provides access to standard HttpRequest properties, like 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 在网页API单元测试?

Is there any way to mock HttpContext.Current.Request.Files for unit testing in Web API?

更新结果
虽然我不知道这会被球队所接受,我不断变化的Post方法使用 Request.Content ,通过的马丁Liversage 的。目前,它看起来是这样的:

Update
Though I'm not sure this will be accepted by the team, I am experimenting with changing the Post method to use Request.Content, as suggested by Martin Liversage. It currently looks something like this:

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!");
}

我的测试类似于这样:

My test looks similar to this:

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

Now I'm getting an error on ReadAsMultipartAsync:

System.IO.IOException:错误写MIME多主体部分输出流。 ---&GT; System.InvalidOperationException:类型MultipartFormDataStreamProvider'的流提供商抛出异常。 ---&GT; System.InvalidOperationException:未找到所需的'内容处置头域MIME多主体部分

推荐答案

网页API已建成通过允许您模拟各种上下文对象以支持单元测试。但是,通过使用 HttpContext.Current 您正在使用旧式的System.Web code使用在的HttpContext 类,这使得它无法单元测试code。

Web API has been built to support unit testing by allowing you to mock various context objects. However, by using HttpContext.Current you are using "old-style" System.Web code that uses the HttpContext class which makes it impossible to unit test your code.

要允许您的code是单元测试,你必须停止使用 HttpContext.Current 。在中的ASP.NET Web API发送HTML表单数据:文件上传和多MIME 你可以看到如何使用Web API来上传文件。讽刺的是,这个code还采用了 HttpContext.Current 来获得访问的MapPath 但是在网页API,你应该使用 HostingEnvironment.MapPath 也工作之外IIS。嘲讽以后也是有问题的,但现在我专注于你的问题有关嘲讽的要求。

To allow your code to be unit testable you have to stop using HttpContext.Current. In Sending HTML Form Data in ASP.NET Web API: File Upload and Multipart MIME you can see how to upload files using Web API. Ironically, this code also uses HttpContext.Current to get access to the MapPath but in Web API you should use HostingEnvironment.MapPath that also works outside IIS. Mocking the later is also problematic but for now I am focusing on your question about mocking the request.

不使用 HttpContext.Current 允许您通过单位分配控制器的 ControllerContext 属性来测试你的控制器:

Not using HttpContext.Current allows you to unit test your controller by assigning the ControllerContext property of the controller:

var content = new ByteArrayContent( /* bytes in the file */ );
content.Headers.Add("Content-Disposition", "form-data");
var controllerContext = new HttpControllerContext {
  Request = new HttpRequestMessage {
    Content = new MultipartContent { content }
  }
};
var controller = new MyController();
controller.ControllerContext = controllerContext;

这篇关于测试使用HttpContext.Current.Request.Files一个Web API的方法?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆