Unit Test and Mock ActionFilter and ActionExecutingContext
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,
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.