Redirects

Redirect to url

_controller.WithCallTo(c => c.Index()).ShouldRedirectTo("http://www.google.com.au/");

Redirect to route name

_controller.WithCallTo(c => c.Index()).ShouldRedirectToRoute("RouteName");

Redirect to action within the same controller

There are a number of ways that you can specify this test, depending on the signature of the action you are redirecting to.

If you are redirecting to an action that takes no parameters, or takes a single int parameter, then you can use a method group, which is the tersest specification (you don't need to specify the parameters to the action), e.g. if these are two actions in the controller you are testing:

public ActionResult ActionWithNoParameters()
{
    return new EmptyResult();
}
public ActionResult RedirectToActionWithNoParameters()
{
    return RedirectToAction("ActionWithNoParameters");
}

Then you can write this test:

_controller.WithCallTo(c => c.RedirectToActionWithNoParameters())
    .ShouldRedirectTo(c => c.ActionWithNoParameters);

We can explicitly define whatever signatures we want to allow this terser syntax, but the different permutations that are possible are infinite and not possible for any custom types in your project. If anyone has ideas for how to do this better let us know!

If you have 1-3 parameters being passed into the action being redirected to then you can still use the method group, but you need to specify the types being passed into the action, e.g. if you have the following controller action being redirected to:

public ActionResult SomeAction(string param1, int param2, bool param3) {}

Then you can write the following test for the redirect:

_controller.WithCallTo(c => c.Index())
    .ShouldRedirectTo<string, int, bool>(c => c.SomeAction);

If you have more than three parameters, or you are uncomfortable with that syntax then you can specify a lambda with a call to the action you want and pass in dummy values for the parameters, e.g. for the previous example:

_controller.WithCallTo(c => c.Index())
    .ShouldRedirectTo(c => c.SomeAction(null, 0, false));

You can also pass through a MethodInfo object against the method you are redirecting to, e.g.:

_controller.WithCallTo(c => c.Index())
    .ShouldRedirectTo(typeof(HomeController).GetMethod("SomeAction"));

We don't recommend using this latter option because it uses a "magic" string so if you change the action name then the string won't change and the test will break and also need to be updated. In saying that, if you change your parameters more often than the action name this might be a better option. If you do use this option be careful that you don't get an AmbiguousMatchException if there are multiple actions with the same name.

At this stage there isn't support for the [ActionName()] attribute or simply passing through a string to check against the action name, but if either are important to you feel free to add an issue in the GitHub project.

Redirect to action in another controller

If you are redirecting to an action in another controller, then there are two syntaxes that you can currently use (similar to the last two mentioned above):

controller.WithCallTo(c => c.Index())
    .ShouldRedirectTo<SomeOtherController>(c2 => c2.SomeAction());

_controller.WithCallTo(c => c.Index())
    .ShouldRedirectTo<SomeOtherController>(typeof(SomeOtherController).GetMethod("SomeAction"));