Próbuję napisać test dla metody Web API, która używa HttpContext.Current.Request.Files
, a po wyczerpujących poszukiwaniach i eksperymentach nie mogę wymyślić, jak się z niej wyśmiewać. Sposób testowany wygląda następująco:Testowanie metody Web API korzystającej z HttpContext.Current.Request.Files?
[HttpPost]
public HttpResponseMessage Post()
{
var requestFiles = HttpContext.Current.Request.Files;
var file = requestFiles.Get(0);
//do some other stuff...
}
Zdaję sobie sprawę, że istnieją other questionssimilar to this, ale one nie dotyczą tej konkretnej sytuacji.
Jeśli próbuję kpić z kontekstu, napotkam problemy z hierarchią obiektów Http*
. Powiedzieć skonfigurować różne obiekty mock (używając Moq) tak:
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);
próbując przypisać go do bieżącego kontekstu ...
HttpContext.Current = mockContext.Object;
... powoduje błąd kompilatora/redline ponieważ to Cannot convert source type 'System.Web.HttpContextBase' to target type 'System.Web.HttpContext'
.
Próbowałem również wiercenia w różnych obiektach kontekstu, które pochodzą z konstruowanym obiektem kontrolera, ale nie można znaleźć jeden, który a) jest obiektem powrotu połączenia HttpContext.Current
w korpusie metody kontrolera i b) zapewnia dostęp do standardowego HttpRequest
właściwości, takie jak Files
.
var requestMsg = controller.Request; //returns HttpRequestMessage
var context = controller.ControllerContext; //returns HttpControllerContext
var requestContext = controller.RequestContext; //read-only returns HttpRequestContext
Ważne jest również, aby pamiętać, że nie mogę zmienić kontroler że jestem testowania w ogóle, więc nie mogę zmienić, aby umożliwić konstruktora kontekst być wstrzykiwany.
Czy jest jakiś sposób na kpiny z HttpContext.Current.Request.Files
dla testów jednostkowych w Web API?
Aktualizacja
Chociaż nie jestem pewien, że to zostanie przyjęte przez zespół, jestem eksperymentować ze zmianą metody POST używać Request.Content
, jak sugeruje Martin Liversage. Obecnie wygląda mniej więcej tak:
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!");
}
Mój test wygląda podobnie do tego:
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) }
}
};
Teraz Dostaję błąd na 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.
Odkładając na bok, jeśli naprawdę nie możesz zmienić kodu, aby usunąć bezpośrednie sprzężenie w zależności od 'HttpContext.Current', istnieje długi sposób na zrobienie tego [przez odbicie] (http: // stackoverflow. com/a/31177399/314291) – StuartLC