title: Testing a Web API method that uses HttpContext.Current.Request.Files?
body: <p>I am attempting to write a test for a Web API method that uses <code>HttpContext.Current.Request.Files</code> and after exhaustive searching and experimentation I cannot figure out how to mock for it.  The method being tested looks like this:</p>
  
  <pre><code>[HttpPost]
  public HttpResponseMessage Post()
  {
      var requestFiles = HttpContext.Current.Request.Files;
      var file = requestFiles.Get(0);
      //do some other stuff...
  }
  </code></pre>
  
  <p>I realize that there are <a href="https://stackoverflow.com/q/21183816/27457">other questions</a> <a href="https://stackoverflow.com/q/1452418/27457">similar to this</a>, but they do not address this specific situation.  </p>
  
  <p>If I attempt to mock the context, I run into issues with the <code>Http*</code> object hierarchy.  Say I set up various mock objects (using <a href="https://github.com/Moq/moq4/wiki/Quickstart" rel="noreferrer">Moq</a>) like this:</p>
  
  <pre><code>var mockFiles = new Mock&lt;HttpFileCollectionBase&gt;();
  mockFiles.Setup(s =&gt; s.Count).Returns(1);
  var mockFile = new Mock&lt;HttpPostedFileBase&gt;();
  mockFile.Setup(s =&gt; s.InputStream).Returns(new MemoryStream());
  mockFiles.Setup(s =&gt; s.Get(It.IsAny&lt;int&gt;())).Returns(mockFile.Object);
  var mockRequest = new Mock&lt;HttpRequestBase&gt;();
  mockRequest.Setup(s =&gt; s.Files).Returns(mockFiles.Object);
  var mockContext = new Mock&lt;HttpContextBase&gt;();
  mockContext.Setup(s =&gt; s.Request).Returns(mockRequest.Object);
  </code></pre>
  
  <p>Attempting to assign it to the current context...</p>
  
  <pre><code>HttpContext.Current = mockContext.Object;
  </code></pre>
  
  <p>...results in a compiler error/redline because it <code>Cannot convert source type 'System.Web.HttpContextBase' to target type 'System.Web.HttpContext'</code>.</p>
  
  <p>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 <code>HttpContext.Current</code> call in the controller method body and b) provides access to standard <code>HttpRequest</code> properties, like <code>Files</code>.</p>
  
  <pre><code>var requestMsg = controller.Request;   //returns HttpRequestMessage
  var context = controller.ControllerContext;  //returns HttpControllerContext
  var requestContext = controller.RequestContext;   //read-only returns HttpRequestContext
  </code></pre>
  
  <p>It is also important to note that <strong>I cannot change the controller that I'm testing at all, so I cannot change the constructor to allow the context to be injected.</strong></p>
  
  <p>Is there any way to mock <code>HttpContext.Current.Request.Files</code> for unit testing in Web API?</p>
  
  <p><strong>Update</strong><br>
  Though I'm not sure this will be accepted by the team, I am experimenting with changing the Post method to use <code>Request.Content</code>, as suggested by <a href="https://stackoverflow.com/users/98607/martin-liversage">Martin Liversage</a>.  It currently looks something like this:</p>
  
  <pre><code>public async Task&lt;HttpResponseMessage&gt; 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!");
  }
  </code></pre>
  
  <p>My test looks similar to this:</p>
  
  <pre><code>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) }
          }
  };
  </code></pre>
  
  <p>Now I'm getting an error on <code>ReadAsMultipartAsync</code>:</p>
  
  <p><code>System.IO.IOException: Error writing MIME multipart body part to output stream. ---&gt; System.InvalidOperationException: The stream provider of type 'MultipartFormDataStreamProvider' threw an exception. ---&gt; System.InvalidOperationException: Did not find required 'Content-Disposition' header field in MIME multipart body part.</code></p>