views:

381

answers:

2

In my Asp.net MVC app, I have two methods on a controller, one for when the user first arrives on the view and then one when they submit the form on said view.

public ActionResult Foo() {}

[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Foo(string id, Account accountToFoo) {}

In the second action, there's a custom model binder that's assembling the account object that I'm acting on, though that's really not important. This all works fine in testing locally on a server.

We try to be pretty good about writing unit tests to test all our different views are properly getting routed to, including those that are HTTP POST. To do so, we've been using mvccontrib's test helper.

Testing gets have been super simple

"~/account/foo/myusername".
       Route().
       ShouldMapTo<AccountController>(c => c.Foo("myusername"));

My question is in testing POST routes, how do I write the lambda that I would use to verify the post is receiving accurate values, similar to the GET test above?

For a POST, it looks something like:

"~/account/foo".
         WithMethod(HttpVerbs.Post).
         ShouldMapTo<AccountController>(a => something_something);

It's the something_something portion of my lambda that I'm having trouble with. Using arbitrary values doesn't work ("a => a.Foo(0, new Account()"). How would I specify the expected values as part of the test?

EDIT I was hoping there was something akin to the way Moq has lambdas for statements such as foo.Setup(s => s.Foo(It.IsAny(), It.Is(i => i > 32)) and so on. Even I have to explicitly supply the values, that's workable--I just can't seem to grok the desired structure to pass those explicit values.

+2  A: 

Here's an example. Assuming you have the following action:

public AccountController : Controller
{
    [AcceptVerbs(HttpVerbs.Post)]
    public ActionResult Foo(string id) 
    {
        return View();
    }
}

And the following route registered:

RouteTable.Routes.MapRoute(
    "Default",
    "{controller}/{action}/{id}",
    new { controller = "home", action = "index", id = "" }
);

You could test it like this:

var routeData = "~/account/foo".WithMethod(HttpVerbs.Post);
routeData.Values["id"] = "123";
routeData.ShouldMapTo<AccountController>(c => c.Foo("123"));

Some tweaking might be necessary to include the second Account argument you have.

Darin Dimitrov
+1  A: 

Using the mvccontrib helper syntax:

"~/account/foo".WithMethod(HttpVerbs.Post).ShouldMapTo<AccountController>(a => a.foo(null));

You pass null as the Foo(string id, Account accountToFoo) method is never executed as part of the routing test.

Paul