C# – Unit testing IAuthenticationFilter in WebApi 2

asp.net-web-apicmoqunit testing

I'm trying to unit test a basic authentication filter I've written for a WebApi 2 project, but i'm having trouble mocking the HttpAuthenticationContext object required in the OnAuthentication call.

public override void OnAuthentication(HttpAuthenticationContext context)
{
    base.OnAuthentication(context);

    var authHeader = context.Request.Headers.Authorization;

    ... the rest of my code here
}

The line in the implementation that I'm trying to set up for mocking is the one that sets the authHeader variable.

However, I can't mock the Headers object because its sealed. And I can't mock the request and set a mocked headers because its a non-virtual property. And so on up the chain all the way to the context.

Has anyone successfully unit tested a new IAuthenticationFilter implementation?

I'm using Moq but I'm sure I could follow along in any mocking library if you have sample code.

Thanks for any help.

Best Answer

It is possible to achieve what you wanted however as none of the objects in the chain context.Request.Headers.Authorization exposes virtual properties Mock or any other framework won't provide much help for you. Here is the code for obtaining HttpAuthenticationContext with mocked values:

HttpRequestMessage request = new HttpRequestMessage();
HttpControllerContext controllerContext = new HttpControllerContext();
controllerContext.Request = request;
HttpActionContext context = new HttpActionContext();
context.ControllerContext = controllerContext;
HttpAuthenticationContext m = new HttpAuthenticationContext(context, null);
HttpRequestHeaders headers = request.Headers;
AuthenticationHeaderValue authorization = new AuthenticationHeaderValue("scheme");
headers.Authorization = authorization;

You just simply need to create in ordinary fashion certain objects and pass them to other with constructors or properties. The reason why I created HttpControllerContext and HttpActionContext instances is because HttpAuthenticationContext.Request property has only get part - its value may be set through HttpControllerContext. Using the method above you might test your filter, however you cannot verify in the test if the certain properties of objects above where touched simply because they are not overridable - without that there is no possibility to track this.