10
votes

I am trying to mock out HttpContext so that I can unit test my controller's Request.IsAuthenicated call. I am using the code that I found at Scott Hanselman's blog to simulate HttpContext using rhino.mocks. so i have this unit test piece:

PostsController postsController = new PostsController(postDL);
mocks.SetFakeControllerContext(postsController);
Expect.Call(postsController.Request.IsAuthenticated).Return(true);

In my controller action, I have something like if(Request.IsAuthenticated).... when I try to run the unit test, the test fails throwing a null exception, and when I try to debug the unit test, I see that the HttpContext is never assigned to the controller. any ideas?

6

6 Answers

8
votes

This should work:

PostsController postsController = new PostsController(postDL);
var context = mocks.Stub<HttpContextBase>();
var request = mocks.Stub<HttpRequestBase>();
SetupResult.For(request.IsAuthenticated).Return(true);
SetupResult.For(context.Request).Return(request);    
postsController.ControllerContext = new ControllerContext(context, new RouteData(), postsController);
1
votes
0
votes

Now, for disclosure, I have yet to get my hands dirty with most of the stuff you are working with, however:

If you want to mock the IsAuthenticated, why not just create a static class to return a bool that can the be manipulated by your test code?

This is a bit rough round the edges, but hopefully you get the idea:

interface IAuthenticationChecker
{
    bool IsAuthenticated { get; }
}

public class MockAuthenticationChecker : IAuthenticationChecker
{
    static bool _authenticated = false;

    public static void SetAuthenticated(bool value)
    {
        _authenticated = value;
    }
    #region IAuthenticationChecker Members

    public bool IsAuthenticated
    {
        get { return _authenticated; }
    }

    #endregion
}

public class RequestAuthenticationChecker : IAuthenticationChecker
{

    #region IAuthenticationChecker Members

    public bool IsAuthenticated
    {
        get {
            if (HttpContext.Current == null)
                throw new ApplicationException(
                    "Unable to Retrieve IsAuthenticated for Request becuse there is no current HttpContext.");

            return HttpContext.Current.Request.IsAuthenticated;
        }
    }

    #endregion
}

You can then use a reference to either at app level, yeah it means you have to add a reference at app level, and you need to use a different ref rather than Request, but you also get complete control over the authentication for testing :)

FYI - this is totally open to being blown apart, I threw it together in about a minute :)

0
votes

Here is one simple way to fake the context, found it from Jeff's blog :

        TextWriter tw = new StringWriter();
        HttpWorkerRequest wr = new SimpleWorkerRequest("/webapp", "c:\\inetpub\\wwwroot\\webapp\\", "default.aspx", "", tw);
        HttpContext.Current = new HttpContext(wr);
0
votes

Here's a class that may be useful. It handles ajax requests, user authentication, request parameters and more: https://gist.github.com/3004119