I am trying to write a test for a Web API method that uses HttpContext.Current.Request.Files , and after exhaustive searching and experimenting, I cannot figure out how to taunt him. The test method is as follows:
[HttpPost] public HttpResponseMessage Post() { var requestFiles = HttpContext.Current.Request.Files; var file = requestFiles.Get(0);
I understand that there are other issues similar to this , but they do not affect this particular situation,
If I try to make fun of the context, I run into problems with the Http* object hierarchy. Let's say I created various mock objects (using Moq ) as follows:
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);
Trying to assign it to the current context ...
HttpContext.Current = mockContext.Object;
... results in a / redline compiler error because it Cannot convert source type 'System.Web.HttpContextBase' to target type 'System.Web.HttpContext' .
I also tried drilling various context objects that come with the constructed controller object, but cannot find one that: a) is the return object of the HttpContext.Current call in the body of the controller method and b) provides access to standard HttpRequest properties, such as Files .
var requestMsg = controller.Request; //returns HttpRequestMessage var context = controller.ControllerContext; //returns HttpControllerContext var requestContext = controller.RequestContext; //read-only returns HttpRequestContext
It is also important to note that I cannot change the controller that I am testing at all, so I cannot change the constructor so that the context can be entered.
Is there any way to trick HttpContext.Current.Request.Files for unit testing in web API?
Update
Although I'm not sure if this will be accepted by the team, I am experimenting with modifying the Post method to use Request.Content , as suggested by Martin Liversage . Currently, it looks something like this:
public async Task<HttpResponseMessage> Post() { var uploadFileStream = new MultipartFormDataStreamProvider(@"C:\temp"); await Request.Content.ReadAsMultipartAsync(uploadFileStream);
My test looks something like 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) } } };
Now I get the ReadAsMultipartAsync error 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.