mvccontrib test helper and verifying http post routes and parameters
Asked Answered
J

2

6

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.

Johnnie answered 29/1, 2010 at 2:52 Comment(2)
Did you ever resolve this problem?Somatoplasm
Nope, never did--and got distracted with other parts of my new app that unit testing these particular POST actions fell by the wayside. Would still love to know how best to approach this.Johnnie
H
15

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.

Helical answered 2/2, 2010 at 10:17 Comment(1)
Oddly enough this scenario doesn't work for me. I have an 2 actions on the same controller, one labelled for HttpGet and one for HttpPost. I can comment out the HttpPost method (same name as the HttpGet, but with a different signature) and my test will still pass using the example you provided in the "You could test it like this" comment above. Here's the link to my question if you have any ideas: #4157661Goutweed
S
2

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.

Somatoplasm answered 10/2, 2010 at 14:44 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.