Используя запрос.Файлы.Считать с помощью TestControllerBuilder из MvcContrib?
-
05-07-2019 - |
Вопрос
У меня есть действие контроллера в ASP.NET MVC, которое обрабатывает загруженные файлы.Однако, похоже, нет никакого способа вызвать Request.Files.Count
при использовании MvcContrib TestControllerBuilder
.
Я знаю, что могу обойти это, абстрагируясь Request.Files
.Мои вопросы таковы:
- Действительно ли это так, что нет прямого способа вызвать
Request.Files.Count
при использованииTestControllerBuilder
?Или я делаю что-то не так? - Есть ли способ заглушить вызов на
Request.Files.Count
во время использованияTestControllerBuilder
используя насмешки над Носорогами? - Как вы думаете, должен ли я отправить запрос или исправление для обработки
Request.Files.Count
в MvcContrib?
Пример кода:
Я хочу убедиться, что в Request.Files
коллекция итак, у меня есть следующее условие в моем действии:
public class MyController : Controller {
public ActionResult Upload() {
if (Request.Files == null || Request.Files.Count == 0)
ViewData.ModelState.AddModelError("File", "Please upload a file");
// do stuff
return View();
}
}
Я использую TestControllerBuilder
из MvcContrib, чтобы создать тестовый дубль для моих тестов контроллера.Однако призыв к Request.Files.Count
кажется, что всегда возникает исключение.Например, выполнение следующего теста NUnit выдает NotImplementedException
во время разговора с controller.Upload()
на призыв к Request.Files.Count
:
[Test]
public void Upload_should_return_default_view_given_one_file() {
MyController controller = new MyController();
TestControllerBuilder controllerBuilder = new TestControllerBuilder();
controllerBuilder.InitializeController(controller);
controllerBuilder.Files["file"] =
MockRepository.GenerateStub<HttpPostedFileBase>();
var result = controller.Upload() as ViewResult;
Assert.That(result.ViewData.ModelState.IsValid, Is.True);
result.AssertViewRendered().ForView(string.Empty);
}
Я также попытался прервать вызов на Request.Files.Count
безрезультатно (я использую Rhino Mocks).Ни одно из приведенных ниже действий не работает (даже если я изменю controller
и/или controllerBuilder
к заглушке):
controllerBuilder.Stub(cb => cb.HttpContext.Request.Files.Count).Return(1);
controller.Stub(c => c.Request.Files.Count).Return(1);
Спасибо
Решение
Я отправил патч на Github для MvcContrib mantainers, но изменения очень просты в внесении, проблема в том, что HttpFileCollectionBase не реализует Count() и методы this[int index], поэтому они должны быть переопределены WriteableHttpFileCollection в MvcContrib.
Я вставляю сюда код для полноты картины, который необходимо добавить в класс WriteableHttpFileCollection:
public override HttpPostedFileBase this[int index]
{
get { return files[AllKeys[index]]; }
}
public override int Count
{
get { return files.Count; }
}
Другие советы
Я использовал этот подход для решения проблемы.
Настройка теста:строковое имя файла = "Тест 1.pdf";FileStream поток = файл.OpenRead("log4net.config");MockRepository макет = новый MockRepository();
builder.Files[fileName] = mock.CreateMock<HttpPostedFileBase>();
using (mock.Record())
{
Expect.Call(builder.Files[fileName].FileName)
.Return(fileName);
Expect.Call(builder.Files[fileName].ContentType)
.Return(contentType);
Expect.Call(builder.Files[fileName].ContentLength)
.Return(Convert.ToInt32(stream.Length.ToString()));
Expect.Call(builder.Files[fileName].InputStream)
.Return(stream);
}
используя макет:
foreach(string key in Request.Files.AllKeys)
{
int lenght = Request.Files[key].ContentLength;
if (lenght > 0)
{
Document document = new Document();
string fileName = Request.Files[key].FileName;
byte[] content= new byte[Convert.ToInt32(lenght)];
Request.Files[key].InputStream.Read(content, 0, content.Length);
document.SetContent(content);
document.MimeType = Request.Files[key].ContentType;
// do whatever you want...
}
}