Saxman
Saxman

Reputation: 5089

ASP.NET MVC - Unit testing, mocking HttpContext without using any mock framework

Since I'm having problem with unit testing RenderPartialViewToString() with Moq framework (ASP.NET MVC - Unit testing RenderPartialViewToString() with Moq framework?), I'm thinking about getting my controller directly, without using Moq for these particular test, however, how do I mocks (or set) the HttpContext for my test without using any Moq framework?

I need to able to do something similar to this, without Moq of course:

    var mockHttpContext = new Mock<ControllerContext>();

    mockHttpContext.SetupGet(p => p.HttpContext.User.Identity.Name).Returns("n1\\test");
    mockHttpContext.SetupGet(p => p.HttpContext.Request.IsAuthenticated).Returns(true);

Thank you very much.

Upvotes: 6

Views: 6965

Answers (2)

Baz1nga
Baz1nga

Reputation: 15579

You can mock it as follows and declare a stringBuilder object that accepts the output.

        var response = new Mock<HttpResponseBase>();
        response.Setup(x => x.Write(It.IsAny<string>())).Callback<string>(y => _stringBuilder.Append(y));
        var url = new Uri("http://localhost/Home/");
        var request = new Mock<HttpRequestBase>();
        request.Setup(x => x.Url).Returns(url);
        request.Setup(x => x.ApplicationPath).Returns("");
        var httpContext = new Mock<HttpContextBase>();
        httpContext.Setup(x => x.Request).Returns(request.Object);
        httpContext.Setup(x => x.Response).Returns(response.Object);

        _controllerContext = new Mock<ControllerContext>();
        _controllerContext.Setup(x => x.HttpContext).Returns(httpContext.Object);
        _homeController = autoMock.Create<HomeController>();
        _homeController.ControllerContext = _controllerContext.Object;

You execute your action as follows:

var action=_homeController.Action(<parameters>);
action.ExecuteResult();

and now your stringbuilder object i.e _stringBuilder will have the result output whatever type it is and you can test it.

Upvotes: 2

Joe Wilson
Joe Wilson

Reputation: 5671

If your controller need authentication info from HttpContext, I would:

  1. Create a new class that wraps the calls you care about. Looks like you want Name and IsAuthenticated. The new class can be AuthenticationService or something.
  2. In the methods/properties in AuthenticationService, call into the real HttpContext, like HttpContext.Current.user.Identity.Name.
  3. Create an interface over the new AuthenticationService with the public methods/properties you care about.
  4. Inject the IAuthenticationService into your controller under test in the constructor. Looks like you may already be doing that with other dependencies in the controller.
  5. Now you can mock IAuthenticationService and it's return values without needing to call into the real HttpContext.

Here are more details from a blog post I did http://www.volaresystems.com/Blog/post/2010/08/19/Dont-mock-HttpContext.aspx. I'm using RhinoMocks instead of Moq, but the concept is the same for staying away from HttpContext.

Upvotes: 3

Related Questions