views:

714

answers:

2

I have a controller action in ASP.NET MVC that handles uploaded files. However, it seems there is no way to call Request.Files.Count while using MvcContrib's TestControllerBuilder.

I know I can work around this by abstracting Request.Files. My questions are:

  1. Is it indeed the case that there is no direct way to call Request.Files.Count when using the TestControllerBuilder? Or am I doing something wrong?
  2. Is there a way to stub the call to Request.Files.Count while using TestControllerBuilder using Rhino Mocks?
  3. Do you think I should submit a request or patch for handling Request.Files.Count to MvcContrib?

Example code:

I want to make sure that there is at least one file in the Request.Files collection so I have the following conditional in my action:

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();
    }
}

I am using the TestControllerBuilder from MvcContrib to create the test double for my controller tests. However, the call to Request.Files.Count always seems to throw a an exception. For example running the following NUnit test throws a NotImplementedException during the call to controller.Upload() at the call to 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);
}

I've also attempted stubbing the call to Request.Files.Count to no avail (I'm using Rhino Mocks). None of the below work (even if I change controller and/or controllerBuilder to a stub):

controllerBuilder.Stub(cb => cb.HttpContext.Request.Files.Count).Return(1);
controller.Stub(c => c.Request.Files.Count).Return(1);

Thanks

A: 

Hi Mike,

I've used this approach to solve the problem.

SetUp the 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);
        }

using the 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...
            }
        }
Marcus Rehm
+1  A: 

I submitted a patch on Github to MvcContrib mantainers, but the changes are very simple to make, the problem is that HttpFileCollectionBase is not implementing Count() and this[int index] methods so they must be overriden by the WriteableHttpFileCollection in MvcContrib.

I paste the code here for completeness, that must be added to WriteableHttpFileCollection class:

public override HttpPostedFileBase this[int index]
{
    get { return files[AllKeys[index]]; }
}

public override int Count
{
    get { return files.Count; }
}
Marc Climent