views:

2260

answers:

4

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?

+1  A: 

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 :)

Rob Cooper
+2  A: 

This may be of some use to you, worked for me in a similar scenario:

http://haacked.com/archive/2007/06/19/unit-tests-web-code-without-a-web-server-using-httpsimulator.aspx

Kieron
Ben Scheirman
@Kieron the link to the source doesn't work
Juri
Try e-mailing Phil via his site - http://haacked.com/contact.aspx
Kieron
+6  A: 

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);
Tim Scott
+1  A: 

Hi, You may find the post I wrote on this to be helpful in some way http://santoshbenjamin.wordpress.com/2008/08/04/mock-httpcontext-and-session-state/

cheers benjy

Santosh Benjamin