Я пытаюсь написать тест для метода Web API, который использует HttpContext.Current.Request.Files
, и после исчерпывающего поиска и экспериментов я не могу понять, как насмехаться над ним. Метод тестируется выглядит следующим образом:Тестирование метода веб-API, использующего HttpContext.Current.Request.Files?
[HttpPost]
public HttpResponseMessage Post()
{
var requestFiles = HttpContext.Current.Request.Files;
var file = requestFiles.Get(0);
//do some other stuff...
}
Я понимаю, что есть other questionssimilar to this, но они не решают эту конкретную ситуацию.
Если я попытаюсь издеваться над контекстом, я столкнулся с проблемами с иерархией объектов Http*
. Скажем, я создал различные фиктивные объекты (используя Moq), как это:
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);
Попытки присвоить его текущий контекст ...
HttpContext.Current = mockContext.Object;
... приводят к ошибке компилятора/красной линии, потому что это Cannot convert source type 'System.Web.HttpContextBase' to target type 'System.Web.HttpContext'
.
Я также попытался выполнить бурение в различных объектах контекста, которые поставляются с построенным объектом контроллера, но не могут найти тот, который: a) является объектом возврата вызова методав теле метода контроллера и b) обеспечивает доступ к стандартным HttpRequest
объектов, таких как Files
.
var requestMsg = controller.Request; //returns HttpRequestMessage
var context = controller.ControllerContext; //returns HttpControllerContext
var requestContext = controller.RequestContext; //read-only returns HttpRequestContext
Важно также отметить, что я не могу изменить контроллер, я тестирование на всех, поэтому я не могу изменить конструктор, чтобы контекст, который будет введен.
Есть ли способ высмеять HttpContext.Current.Request.Files
для модульного тестирования в Web API?
Update
Хотя я не уверен, что это будет принято командой, я экспериментировал с изменением метода Post использовать Request.Content
, как это было предложено Martin Liversage. В настоящее время она выглядит примерно так:
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!");
}
Мой тест выглядит примерно так:
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) }
}
};
Теперь я получаю ошибку на 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.
В качестве альтернативы, если вы действительно не можете изменить свой код, чтобы удалить прямую связь с зависимостью «HttpContext.Current», существует длинный отложенный способ сделать это [через отражение] (http: // stackoverflow. com/a/31177399/314291) – StuartLC