Testen eines Web-API-Methode, die verwendet HttpContext.Aktuelle.Anfrage.Dateien?
Ich bin versucht zu schreiben, einen test für eine Web-API-Methode, die verwendet HttpContext.Current.Request.Files
und nach eingehendem suchen und Experimentieren kann ich nicht herausfinden, wie zum Hohn für ihn. Getesteten Methode sieht wie folgt aus:
[HttpPost]
public HttpResponseMessage Post()
{
var requestFiles = HttpContext.Current.Request.Files;
var file = requestFiles.Get(0);
//do some other stuff...
}
Ich weiß, dass es andere Fragen ähnlich wie diese, aber Sie tun es nicht auf diese bestimmte situation.
Wenn ich versuche zu verspotten, den Zusammenhang hatte ich Probleme mit der Http*
Objekt-Hierarchie. Sagen, dass ich verschiedene mock-Objekte (mit Moq) wie folgt:
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);
Versucht, weisen Sie dem aktuellen Kontext...
HttpContext.Current = mockContext.Object;
...führt zu einem compiler-Fehler/redline, weil es Cannot convert source type 'System.Web.HttpContextBase' to target type 'System.Web.HttpContext'
.
Ich habe auch versucht, bohren in verschiedenen Kontext-Objekte, die mit der gebauten controller-Objekt, aber nicht finden können, eine, ein) ist das Rückgabe-Objekt ein HttpContext.Current
Aufruf der controller-Methode Körper und b) haben Sie Zugriff auf standard - HttpRequest
Eigenschaften, wie Files
.
var requestMsg = controller.Request; //returns HttpRequestMessage
var context = controller.ControllerContext; //returns HttpControllerContext
var requestContext = controller.RequestContext; //read-only returns HttpRequestContext
Es ist auch wichtig zu beachten, dass die ich nicht ändern kann, den controller, den ich Teste, so kann ich nicht ändern Sie den Konstruktor zu ermöglichen, den Kontext injiziert werden.
Gibt es eine Möglichkeit, zu verspotten HttpContext.Current.Request.Files
für unit-testing in Web-API?
Update
Obwohl, ich bin mir nicht sicher, ob dies akzeptiert wird von der Mannschaft, ich bin das Experimentieren mit dem ändern der Post-Methode zu verwenden Request.Content
, wie vorgeschlagen, durch Martin Liversage. Derzeit sieht ungefähr so aus:
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!");
}
Mein test sieht wie folgt aus:
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) }
}
};
Nun ich bin immer ein Fehler auf 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.
- Als beiseite, wenn Sie können nicht wirklich ändern, Ihren code zu löschen, die direkte Kopplung auf die
HttpContext.Current
Abhängigkeit, es ist eine langatmige Art zu tun diese per reflection
Du musst angemeldet sein, um einen Kommentar abzugeben.
Web-API wurde gebaut, um die Unterstützung von unit-Tests, indem Sie mock verschiedenen Kontext-Objekte. Aber mit
HttpContext.Current
Sie mit "old-style"System.Web
code, der verwendet dieHttpContext
Klasse, die es unmöglich macht unit-test-code.Zu ermöglichen, Ihren code auf sein Gerät getestet haben Sie zu stoppen, mit
HttpContext.Current
. In Senden von HTML-Formular Daten in ASP.NET Web-API: File Upload und " Multipart MIME kann man sehen, wie das hochladen von Dateien über Web-API. Ironischerweise, dieser code wird auch verwendetHttpContext.Current
Zugang zu denMapPath
aber in der Web-API, die Sie verwenden solltenHostingEnvironment.MapPath
dass auch arbeiten außerhalb der IIS. Die Verspottung später ist auch problematisch, aber jetzt konzentriere ich mich auf Ihre Frage über die Verspottung der Anfrage.Nicht mit
HttpContext.Current
können Sie unit-testen Sie Ihre controller durch die Zuordnung derControllerContext
Eigenschaft des Controllers:Content-Disposition
header des inneren Inhalts, nicht auf die multi-part Inhalt.Die akzeptierte Antwort ist perfekt für die OP ' s Frage. Wollte ich hinzufügen, dass meine Lösung hier, die sich von Martin ' s, da dies die Seite, die ich angewiesen wurde, bei der Suche einfach auf, wie zum Hohn aus dem Request-Objekt für die Web-API, so kann ich hinzufügen, Header, mein Controller ist auf der Suche nach. Ich hatte eine schwierige Zeit der Suche die einfache Antwort:
Und es gibt Sie; eine sehr einfache Möglichkeit zum erstellen von controller-context, mit dem Sie "Mock" aus dem Request-Objekt und übergeben Sie die korrekten Header für Ihre Controller-Methode.
Verspottet ich nur die geposteten Datei. Ich glaube, dass alle Dateien können auch verspottet diese Weise.