Sto tentando di scrivere un test per un metodo API Web che utilizza HttpContext.Current.Request.Files
e dopo una ricerca esauriente e una sperimentazione non riesco a capire come deriderlo. Il metodo in fase di sperimentazione è simile al seguente:Test di un metodo API Web che utilizza HttpContext.Current.Request.Files?
[HttpPost]
public HttpResponseMessage Post()
{
var requestFiles = HttpContext.Current.Request.Files;
var file = requestFiles.Get(0);
//do some other stuff...
}
mi rendo conto che ci sono other questionssimilar to this, ma non affrontano questa situazione specifica.
Se tento di simulare il contesto, mi imbatto in problemi con la gerarchia di oggetti Http*
. Dì che impostare vari oggetti fittizi (utilizzando Moq) come questo:
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);
tentativo di assegnare al contesto attuale ...
HttpContext.Current = mockContext.Object;
... produce un errore di compilatore/redline perché it Cannot convert source type 'System.Web.HttpContextBase' to target type 'System.Web.HttpContext'
.
Ho anche provato a eseguire il drill in vari oggetti di contesto forniti con l'oggetto controller costruito, ma non riesco a trovarne uno a) è l'oggetto di ritorno di una chiamata HttpContext.Current
nel corpo del metodo controller eb) fornisce accesso allo standard HttpRequest
proprietà, come Files
.
var requestMsg = controller.Request; //returns HttpRequestMessage
var context = controller.ControllerContext; //returns HttpControllerContext
var requestContext = controller.RequestContext; //read-only returns HttpRequestContext
E 'anche importante notare che non posso cambiare il controller che sto testando affatto, quindi non può cambiare il costruttore per consentire il contesto da iniettare.
Esiste un modo per simulare lo HttpContext.Current.Request.Files
per il test dell'unità nell'API Web?
Aggiornamento
Anche se non sono sicuro che questo sarà accettata dal team, sto sperimentando con cambiando il metodo POST per usare Request.Content
, come suggerito da Martin Liversage. E 'attualmente simile a questa:
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!");
}
Il mio test è simile a questo:
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) }
}
};
Ora sto ottenendo un errore sul 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.
Per inciso, se davvero non è possibile modificare il codice per rimuovere l'accoppiamento diretto sulla dipendenza 'HttpContext.Current', c'è un modo prolisso di fare [questo tramite riflessione] (http: // StackOverflow. it/a/31177399/314291) – StuartLC