Utilizzando Request.Files.Count con TestControllerBuilder di MvcContrib?
-
05-07-2019 - |
Domanda
Ho un'azione del controller in ASP.NET MVC che gestisce i file caricati. Tuttavia, sembra che non ci sia modo di chiamare Request.Files.Count
mentre si utilizza TestControllerBuilder
di MvcContrib.
So di poter aggirare questo problema astraggendo Request.Files
. Le mie domande sono:
- È davvero vero che non esiste un modo diretto per chiamare
Request.Files.Count
quando si utilizzaTestControllerBuilder
? O sto facendo qualcosa di sbagliato? - Esiste un modo per bloccare la chiamata a
Request.Files.Count
mentre si utilizzaTestControllerBuilder
utilizzando Rhino Mocks? - Pensi che dovrei inviare una richiesta o una patch per la gestione di
Request.Files.Count
a MvcContrib?
Codice di esempio:
Voglio assicurarmi che ci sia almeno un file nella raccolta Request.Files
, quindi ho la seguente condizione nella mia azione:
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();
}
}
Sto usando il TestControllerBuilder
di MvcContrib per creare il doppio di test per i test del mio controller. Tuttavia, la chiamata a Request.Files.Count
sembra sempre generare un'eccezione. Ad esempio, l'esecuzione del seguente test NUnit genera un NotImplementedException
durante la chiamata a controller.Upload ()
alla chiamata a 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);
}
Ho anche tentato di reimpostare la chiamata su Request.Files.Count
senza alcun risultato (sto usando Rhino Mocks). Nessuna delle operazioni seguenti (anche se cambio controller
e / o controllerBuilder
in uno stub):
controllerBuilder.Stub(cb => cb.HttpContext.Request.Files.Count).Return(1);
controller.Stub(c => c.Request.Files.Count).Return(1);
Grazie
Soluzione
I ho inviato una patch su Github a MvcContrib mantainers, ma le modifiche sono molto semplice da risolvere, il problema è che HttpFileCollectionBase non implementa i metodi Count () e questo [int index], quindi devono essere sostituiti da WriteableHttpFileCollection in MvcContrib.
Ho incollato il codice qui per completezza, che deve essere aggiunto alla classe WriteableHttpFileCollection:
public override HttpPostedFileBase this[int index]
{
get { return files[AllKeys[index]]; }
}
public override int Count
{
get { return files.Count; }
}
Altri suggerimenti
Ho usato questo approccio per risolvere il problema.
Imposta il test: string fileName = " Test 1.pdf " ;; FileStream stream = File.OpenRead (" log4net.config "); MockRepository mock = new 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);
}
usando il mock:
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...
}
}