Ich versuche, einen Test für eine Web-API-Methode zu schreiben, die HttpContext.Current.Request.Files
verwendet, und nach erschöpfenden Suchen und Experimentieren kann ich nicht herausfinden, wie man dafür spottet. Das Verfahren getestet wird, sieht wie folgt aus:Testen einer Web-API-Methode, die HttpContext.Current.Request.Files verwendet?
[HttpPost]
public HttpResponseMessage Post()
{
var requestFiles = HttpContext.Current.Request.Files;
var file = requestFiles.Get(0);
//do some other stuff...
}
ich erkennen, dass es other questionssimilar to this, aber sie haben nicht diese spezifische Situation befassen.
Wenn ich versuche, den Kontext zu verspotten, stoße ich auf Probleme mit der Objekthierarchie . Sagen wir, ich verschiedene Mock-Objekte (mit Moq) wie folgt ein:
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);
Der Versuch, es zu den aktuellen Kontext zuordnen ...
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 verschiedene Kontextobjekte, die mit dem konstruierten Controller-Objekt kommen, aber nicht finden, dass a) ist das Rückgabeobjekt eines HttpContext.Current
Aufruf in der Controller-Methode body und b) bietet 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 Ich kann den Controller ändern, die ich überhaupt testen, so kann ich nicht den Konstruktor ändert der Kontext zu ermöglichen, injiziert werden.
Gibt es eine Möglichkeit, HttpContext.Current.Request.Files
für Unit-Tests in Web-API zu verspotten?
aktualisiert
Obwohl ich nicht sicher bin, wird vom Team akzeptiert werden, experimentiere ich die Post-Methode mit wechselnden Request.Content
zu verwenden, wie von Martin Liversage vorgeschlagen. Es sieht derzeit so etwas wie dieses:
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 in etwa so aussieht:
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 einen Fehler auf ReadAsMultipartAsync
Ich erhalte:
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.
Wenn Sie nicht wirklich Ihren Code ändern können, um die direkte Kopplung für die 'HttpContext.Current'-Abhängigkeit zu entfernen, gibt es einen langen Weg [dies über Reflektion] (http: // stackoverflow. com/a/31177399/314291) – StuartLC