How to Unit Test Attributes are Applied to MVC Web API Controller Methods

A Very Simple Guide

George Marklow

--

Photo by Christina Rumpf on Unsplash

Introduction

This article explains how to test that an attribute is applied to a controller method. We will create an attribute, write a test and then apply the attribute in a TDD manner.

Before Starting

Though not essential, you might want to check out this article I wrote, since this tutorial continues using that code.

The Code

Create the Attribute

I’ve created an attribute AccessDeniedExceptionAttribute, which doesn’t have any implementation as its beyond the scope of this article.

using Microsoft.AspNetCore.Mvc.Filters;namespace Shop.Attributes
{
public class AccessDeniedExceptionAttribute : ExceptionFilterAttribute
{
public override void OnException(ExceptionContext context)
{
// Implementation
// ..
}
}
}

In a real-world case, this class would be injected with an instance of IHttpContextAccessor to find the name and id of the user who got blocked, as well as an instance of ILogger to log the attempted access with the user details.

Add the Test

Run the following test case, which will fail because you haven’t yet applied the AccessDeniedExceptionAttribute attribute to the controller method:

[Test]
public void Get_Should_Be_Decorated_With_AccessDeniedExceptionAttribute()
{
// arrange
var controllerType = typeof(ProductController);
var methodName = nameof(ProductController.Get);
var attributeType = typeof(AccessDeniedExceptionAttribute);
var methodInfo = controllerType.GetMethod(methodName);
var methodAttributes = methodInfo.GetCustomAttributes(false);
// act
var isAttributeApplied = methodAttributes.Any(x => x.GetType() == attributeType);
// assert
Assert.IsTrue(isAttributeApplied);
}

Add the Attribute to the Controller Method

Finally, decorate the controller method you’re testing and re-run the test to show it now passes.

// GET: api/product
[HttpGet]
[AccessDeniedExceptionAttribute]
public IEnumerable<Product> Get()
{
return _productService.GetProducts();
}

Improvements to the code

The following part of the test logic will need to be repeated for every controller method decorated with an attribute:

[Test]
public void Get_Should_Be_Decorated_With_AccessDeniedExceptionAttribute()
{
[...]
var methodInfo = controllerType.GetMethod(methodName);
var methodAttributes = methodInfo.GetCustomAttributes(false);
var isAttributeApplied = methodAttributes
.Any(x => x.GetType() == attributeType);
[...]
}

This is not ideal, so it makes sense to place the part of the test logic into a static helper class.

Here’s the code for the static method that would handle this logic, which would be called from the controller test (which would then itself be unit tested in isolation):

public static bool IsDecoratedWithAttribute(Type controllerType, Type attributeType, string methodName)
{
var methodInfo = controller.GetMethod(methodName);
var methodAttributes = methodInfo.GetCustomAttributes(false);

return methodAttributes
.Any(x => x.GetType() == attributeType);
}

Thanks for reading! Let me know what you think in the comments section below, and don’t forget to subscribe. 👍

--

--

George Marklow

George is a software engineer, author, blogger, and abstract artist who believes in helping others to make us happier and healthier.