Unit Test and Mock ActionFilter and ActionExecutingContext

Unit Test and Mock ActionFilter

Today in this article we shall see how to Unit Test and Mock ActionFilter and mock ActionExecutingContext classes often useful for testing the controller logic in the API or ASP.NET Core MVC application.

You can use the below-discussed approach using the XUnit or NUnit or MSTest framework of your choice.

Unit test cases of controller-specific methods make API robust and help identify any breaking changes early.

We shall use below sample code below where the controller is attributed with filter attribute i.e ApiInputInterceptor attribute as shown below example,

Mock OnActionExecuting and ActionFilter

The controller with action filters includes the below-listed methods. These methods wrap the filters that run for a given action,

  • OnActionExecuting – runs before any of the action’s filters.
  • OnActionExecuted – runs after all of the action’s filters.
  • Or OnActionExecutionAsync– async format

Below is the simplified implementation of the ApiInputInterceptor for demonstration purposes,

public class ApiInputInterceptor : ActionFilterAttribute,IActionFilter
    {
   
        public override void OnActionExecuting(ActionExecutingContext context)
        {
            // do something before
            if (!context.ActionArguments.ContainsKey("Id"))
            {
                context.Result = new BadRequestObjectResult("The id must be passed as parameter");
                return;
            }
        }
        public override void OnActionExecuted(ActionExecutedContext context)
        {
            //throw new NotImplementedException();
        }
    }

Let’s now create the Unit test case for this Action filter attribute which is of type ApiInputInterceptor

Step 1- Create Mock of ActionContext

Below is a simple way of creating a mock of ActionContext. This mock object will be needed in the next steps where we will create a mock setup for ActionExecutingContext.

Below we are creating a mock object of HttpContext, RouteData, and ActionDescriptor using the moq library.

 var actContext = new ActionContext(
                Mock.Of<HttpContext>(),
                Mock.Of<RouteData>(),
                Mock.Of<ActionDescriptor>(),
                Mock.Of<ModelStateDictionary>()
            );

Step 2- Create Mock of ActionExecutingContext

Let’s now create the mock for ActionExecutingContext using the mock action context object as defined above. We are also passing a mock list of IFilterMetadata and Dictionary key-value pairs.

var actExecutingContext = new ActionExecutingContext(
                actionContext,
                new List<IFilterMetadata>(),
                new Dictionary<string, object>(),
                Mock.Of<Controller>()
            );

Step 3: Define action arguments for GET or POST method

If input arguments expect an input with the name “id” then please define it as below,

Example

 actionExecutingContext.ActionArguments["Id"] = "123";

If action arguments expect a complex type as arguments especially in case POST operation then below is a sample example on defining the complex or class object as an action argument.

Example

var source = new Source
            {
                FirstName = "ABCD",
                Address = "USA",
                Id = "1232"
            };
actionExecutingContext.ActionArguments["Id"] = source;

Let’s define the action by creating the instance of ValidateInputAttribute and executing the OnActionExecuting method

 //Act

  var valInputObject = new ApiInputInterceptor();
  valInputObject.OnActionExecuting(actionExecutingContext);

Step 4: Define Assert

We are making sure the result of validation fails reports BadRequestObjectResult as shown below,

Assert.IsType<BadRequestObjectResult>(actionExecutingContext.Result);

Useful References

Do you have any comments or ideas or any better suggestions to share?

Please sound off your comments below.

Happy Coding !!



Please bookmark this page and share it with your friends. Please Subscribe to the blog to receive notifications on freshly published(2024) best practices and guidelines for software design and development.



Leave a Reply

Your email address will not be published. Required fields are marked *