Mock HttpActionContext for Unit Test

9.7k views Asked by At

I have a custom authorization attribute seen below and I am trying to write a unit test to test its functionality.

    public override void OnAuthorization(System.Web.Http.Controllers.HttpActionContext actionContext)
    {
        if (actionContext.Request.Headers.Authorization != null)
        {
            // get the Authorization header value from the request and base64 decode it
            string userInfo = Encoding.Default.GetString(Convert.FromBase64String(actionContext.Request.Headers.Authorization.Parameter));

            // custom authentication logic
            if (string.Equals(userInfo, string.Format("{0}:{1}", "user", "pass")))
            {
                IsAuthorized(actionContext);
            }
            else
            {
                HandleUnauthorizedRequest(actionContext);
            }
        }
        else
        {
            HandleUnauthorizedRequest(actionContext);
        }
    }

    protected override void HandleUnauthorizedRequest(System.Web.Http.Controllers.HttpActionContext actionContext)
    {
        actionContext.Response = new HttpResponseMessage(System.Net.HttpStatusCode.Unauthorized)
        {
            ReasonPhrase = "Unauthorized"
        };
    }

My problem is that when I try to test this I get "System.NullReferenceException: Object reference not set to an instance of an object." I have tried to set the actionContext's request.headers.authorization value but it has no setter. When I try mocking the HttpActionContext it says it cannot convert from a mock HttpActionContext to a real one. Below is my test code

public class HttpBasicAuthorizeAttributeTest
{
    private HttpBasicAuthorizeAttribute ClassUnderTest { get; set; }

    private HttpActionContext actionContext { get; set; }

    [TestMethod]
    public void HttpBasicAuthorizeAttribute_OnAuthorize_WithAuthorizedUser_ReturnsAuthorization()
    {
       var context = new Mock<HttpActionContext>();
       context.Setup(x => x.Request.Headers.Authorization.Parameter).Returns("bzUwkDal=");
       ClassUnderTest.OnAuthorization(context);
    }

    [TestInitialize]
    public void Initialize()
    {
        ClassUnderTest = new HttpBasicAuthorizeAttribute();
        actionContext = new HttpActionContext();
    }
}

*Left out the assert until I can even get the HttpActionContext to work

1

There are 1 answers

7
Nkosi On BEST ANSWER

You can use the actual objects and provide it to the mock in order to exercise the method under test as Moq in unable to mock the non-virtual members.

[TestMethod]
public void HttpBasicAuthorizeAttribute_OnAuthorize_WithAuthorizedUser_ReturnsAuthorization() {
   //Arrange
    var context = new HttpActionContext();
    var headerValue = new AuthenticationHeaderValue("Basic", "bzUwkDal=");
    var request = new HttpRequestMessage();
    request.Headers.Authorization = headerValue;
    var controllerContext = new HttpControllerContext();
    controllerContext.Request = request;
    context.ControllerContext = controllerContext;

   //Act
   ClassUnderTest.OnAuthorization(context);

   //Assert
   //...
}