0

When using ASP.Net Core 2 MVC and FluentAssertions.AspNetCore.Mvc, how do I assert that a controller redirected to an action?

For example, given the following controller action:

public IActionResult SomeAction() {
  return RedirectToAction("SomeOtherAction");
}

How would I write a test verifying the redirection?

I'm looking for something like:

[Fact]
public void SomeActionTest() {
  var controller = new SomeController();
  var result = controller.SomeAction();

  result.Should().BeRedirectedToRouteResult().WithAction("SomeOtherAction");
}

...except instead of BeRedirectedToRouteResult().WithAction("SomeOtherAction"), I'm looking to assert something like BeRedirectedToAction("SomeOtherAction").

Ben Gribaudo
  • 5,057
  • 1
  • 40
  • 75

1 Answers1

1

I personally would do something like the following:

Creating a static class containing the extension method and assertion class, which has a method called BeRedirectAction and then can be used like the following:

    [Fact]
    public void ActionReturnsView_ExpectedRedirectToError_TypeMismatch()
    {
        var controller = new HomeController();

        var result = controller.Index();

        result.Should().BeRedirectAction(nameof(HomeController.Error));
    }

Extension Method + Assertion Class

Example Static class

public static class ActionResultAssertionExtensions
{
    public class ActionResultAssertions : ObjectAssertions
    {
        public new IActionResult Subject { get; }

        public ActionResultAssertions(IActionResult subject) : base(subject)
        {
            Subject = subject;
        }

        [CustomAssertion]
        public void BeRedirectAction(string actionName, string because= null, params object[] becauseArgs)
        {
            var redirectResult = AssertionExtensions.Should(Subject).BeOfType<RedirectToActionResult>().Which;

            var actual = redirectResult.ActionName;
            var expected = actionName;

            Execute.Assertion.ForCondition(actual == expected)
                .BecauseOf(because, becauseArgs)
                .FailWith("Expected {context} to redirect to {0} Action but it is redirecting to {1}", expected, actual);
        }
    }

    public static ActionResultAssertions Should(this IActionResult subject)
    {
        return new ActionResultAssertions(subject);
    }
}

Sample Tests

Type Mismatch Test

This is an example failure of when the result is not a redirect:

    [Fact]
    public void ActionReturnsView_ExpectedRedirectToError_TypeMismatch()
    {
        var controller = new HomeController();

        var result = controller.Index();

        result.Should().BeRedirectAction(nameof(HomeController.Error));
    }

Result:

Expected type to be Microsoft.AspNetCore.Mvc.RedirectToActionResult, but found Microsoft.AspNetCore.Mvc.ViewResult.

Success Test

This is an example of a passing test

    [Fact]
    public void ActionRedirectsToError_ExpectedRedirectToError_TestShouldPass()
    {
        var controller = new HomeController();

        var result = controller.RedirectToError();

        result.Should().BeRedirectAction(nameof(HomeController.Error));
    }

Different Action Test

This is an example of a test failure when it gets redirected to a different action:

    [Fact]
    public void ActionRedirectsToIndex_ExpectedRedirectToError_TestSHouldFailSayingDifferentActionName()
    {
        var controller = new HomeController();

        var result = controller.RedirectToIndex();

        result.Should().BeRedirectAction(nameof(HomeController.Error));
    }

Result:

Expected result to redirect to "Error" Action but it is redirecting to "Index"

N.B.

The above does not test for controller/area differences, or any other potential combinations, it just looks at the Action Name.

Michal Ciechan
  • 13,492
  • 11
  • 76
  • 118
  • Thanks, Michal! Would you ever consider submitting this as a pull request to FluentAssertions? – Ben Gribaudo Jun 07 '18 at 20:24
  • @BenGribaudo this is a framework (ASP.NET Core 2.0) specific assertion, so definitely not into the standard FA repo, maybe worth having another repo that provides these extensions specifically for ASP.NET Core 2.0 (if there isn't one already) – Michal Ciechan Jun 08 '18 at 09:01
  • Maybe a submission to https://github.com/fluentassertions/fluentassertions.aspnetcore.mvc? – Ben Gribaudo Jun 08 '18 at 17:31