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")
.
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));
}
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);
}
}
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.
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));
}
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"
The above does not test for controller/area differences, or any other potential combinations, it just looks at the Action Name.