“Not everything needs to be unit-tested” but you shouldn’t make the previously mentioned phrase as an excuse to not to do unit tests. When it comes to C# filters even though you’re using them your actions in the controller when doing unit-tests their execution logic will not be considered as you’re directly invoking the actions. In most cases, integration tests are performed to make sure the filters such as authorization filter (
[Authorization]) and/or other attributes are taken into consideration.
In case of writing your own custom filter in some cases, as it was written by you, you are responsible to make sure that unit (the class itself which is derived from any filter interfaces (eg:
Attribute abstract class) is tested.
In this post, let’s see how we can unit test a custom authorization filter, which is used to authorize an action based on a pre-defined API key which is stored in the application settings. lets start writing the unit tests. We are going to use Xunit and Moq for this purpose.
Planning the Unit Test
OnAuthorization method of the concrete implementation of our custom filter which derives from
IAuthorizationFilter interface is the method that needs to be tested in the case of authorization, as this method will be invoked when the framework calls the particular action in the controller.
We can set the result of the given http context to
UnauthorizedResult if the expected
Authorization header is not present or present with wrong value in the action called by the client, which will eventually be the final result if over-ridden as unauthorized.
This method, as per the given definition, expects an object of type
AuthorizationFilterContext as the parameter. So we need to construct the object first. The constructor of the
AuthorizationFilterContext class expects two parameters:
- List of items derived from
For this, we need to create an
ActionContext object, while one of the constructor of the
ActionContext class gives the possibility to have the
HttpContext object which eventually carries the header information for authorization along with some other parameters such as route data and action descriptor. Using this constructor to construct the
ActionContext will be the most suitable way as we can define the
Authorization header using that.
Since we’re checking for the API key from the app settings, we should mock the AppSettings (consider, we have only one object in the app settings called “ApiKey”) using moq framework as below:
HttpContext again can be mocked to have
Authorization header as below:
Later using the above mocked
httpContextMock.Object we can create a fake
ActionContext object as below:
AuthorizationFilterContext , a fake object can be created as below:
Now we’ve arranged all the dependencies, let’s perform the “act” now by creating the custom authorization filter class as below:
and calling the
OnAuthorization method of our custom authorization filter by passing the already arranged
authFilterContext object of the
ApiKeyAuthorizeAttribute type as below:
Finally, we can perform the assert by checking if this call sets the
Result of the
authFilterContext , which will be the actual result of the HTTP call – to the type
UnauthorizedResult as per the given logic in the custom authorization attribute since we’ve defined a different API key in the mock header than the expected one which is mocked in the App Settings mock: