views:

519

answers:

2

I’m just learning ASP.NET MVC and I’m trying to create a mock form request for a unit test.

I’m using RhinoMocks.

I have looked at the following websites but cannot get these to work.

http://blog.maartenballiauw.be/post/2008/03/19/ASPNET-MVC-Testing-issues-Q-and-A.aspx

Update: Controller Code:

    /// <summary>
    /// Creates a new entry
    /// </summary>
    /// <returns></returns>
    [AcceptVerbs(HttpVerbs.Post)]
    public ActionResult Create([Bind()]Person person) 
    {
        if (Request.Form["DateOfBirth"].ToString() == "")
        {
            TempData["message"] = "Please select a date of Birth";
            ViewData["DateOfBirth"] = Request.Form["DateOfBirth"].ToString();

            MvcValidationAdapter.TransferValidationMessagesTo(ViewData.ModelState, person.ValidationMessages);
            return View();
        }
        else
        { 

        if (person.IsValid())
        {
            person.DateOfBirth = Convert.ToDateTime(Request.Form["DateOfBirth"]);

            personRepository.SaveOrUpdate(person);
            TempData["message"] = person.Firstname + " was successfully added";
            return RedirectToAction("Create", "OrderDetails", new { id = person.ID });
        }
        else
        {

            ViewData["DateOfBirth"] = Request.Form["DateOfBirth"].ToString();

            MvcValidationAdapter.TransferValidationMessagesTo(ViewData.ModelState, person.ValidationMessages);
            return View();
        }

        }

    }
A: 

If you change the action method to have a FormCollection as the final parameter you can then pass in a FormCollection instance that contains all your values. The MVC framework will automatically pass in the values from the form within that parameter when running live.

public ActionResult MyMethod(FormCollection form)
{
    // in testing you will pass in a populated FormCollection object
    // at runtime the framework will populate the form parameter with
    // the contents of the posted form
}

Here is a reasonable example of it being used.

Edit

Have you tried this:

    /// <summary>
    /// Creates a new entry
    /// </summary>
    /// <returns></returns>
    [AcceptVerbs(HttpVerbs.Post)]
    public ActionResult Create([Bind()]Person person, FormCollection form) 
    {
        if (form["DateOfBirth"].ToString() == "")
        {
            TempData["message"] = "Please select a date of Birth";
            ViewData["DateOfBirth"] = form["DateOfBirth"].ToString();

            MvcValidationAdapter.TransferValidationMessagesTo(
                ViewData.ModelState, person.ValidationMessages);
            return View();
        }
        else
        { 

        if (person.IsValid())
        {
            person.DateOfBirth = Convert.ToDateTime(form["DateOfBirth"]);

            personRepository.SaveOrUpdate(person);
            TempData["message"] = 
                person.Firstname + " was successfully added";
            return RedirectToAction(
                "Create", "OrderDetails", new { id = person.ID });
        }
        else
        {

            ViewData["DateOfBirth"] = form["DateOfBirth"].ToString();

            MvcValidationAdapter.TransferValidationMessagesTo(
                ViewData.ModelState, person.ValidationMessages);
            return View();
        }

        }

    }
Garry Shutler
Thanks, I still cannot get this to work. Is there any other examples?
Roslyn
Any chance of editing your question with some code? The action method and your test code perhaps?
Garry Shutler
That's the unit test working now. Thanks for all your help.
Roslyn
Excellent. No problem.
Garry Shutler
A: 

Unless you're testing MVC itself, shouldn't you be mainly testing that the controller's action does the right thing with the arguments passed by the framework?

You can probably mock more indirect form access via:

controller.ActionInvoker.InvokeAction(ctx);

where ctx is a ControllerContext, with the form data etc. Here's an example using rhino to provide the context (MoQ also shown).

Marc Gravell