Essai d'une API Web méthode qui utilise HttpContext.Actuel.Demande.Fichiers?

J'essaie d'écrire un test pour une Web API méthode qui utilise HttpContext.Current.Request.Files et, après une recherche et d'expérimentation je ne peux pas comprendre comment, à se moquer. La méthode testée ressemble à ceci:

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

Je me rends compte qu'il y a d'autres questions similaire à ce, mais ils ne traitent pas de cette situation spécifique.

Si je tente de simuler le contexte, je rencontre des problèmes avec le Http* hiérarchie d'objets. Dire que j'ai mis en place divers objets fantaisie (à l'aide de Moq) comme ceci:

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

Tentant de l'attribuer le contexte actuel...

HttpContext.Current = mockContext.Object;

...génère une erreur de compilation/redline, car il Cannot convert source type 'System.Web.HttpContextBase' to target type 'System.Web.HttpContext'.

J'ai aussi essayé de forage dans divers contexte des objets qui viennent avec la construction de l'objet contrôleur, mais ne pouvez pas en trouver un qui a) est l'objet de retour d'un HttpContext.Current appel à la méthode de contrôleur corps et b) permet d'accéder à la norme HttpRequest propriétés, comme Files.

var requestMsg = controller.Request;   //returns HttpRequestMessage
var context = controller.ControllerContext;  //returns HttpControllerContext
var requestContext = controller.RequestContext;   //read-only returns HttpRequestContext

Il est également important de noter que je ne peux pas changer le contrôleur que je suis en essais à tous, donc je ne peux pas changer le constructeur pour permettre le contexte pour être injecté.

Est-il une manière de se moquer de HttpContext.Current.Request.Files pour les tests unitaires dans l'API Web?

Mise à jour

Si je ne suis pas sûr que cela va être accepté par l'équipe, je suis expérimenter avec la modification de la méthode Post pour utiliser Request.Content, comme suggéré par Martin Liversage. Actuellement, il ressemble à quelque chose comme ceci:

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

Mon test ressemble à ceci:

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

Maintenant j'ai une erreur sur 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.

En aparté, si vous avez vraiment ne pouvez pas modifier votre code pour supprimer le couplage direct sur le HttpContext.Current de dépendance, il est un de longue haleine façon de faire ce par le biais d'une réflexion

OriginalL'auteur AJ. | 2015-07-02