Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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.

like image 777
Saxman Avatar asked Sep 07 '10 18:09

Saxman


2 Answers

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.

like image 89
Joe Wilson Avatar answered Oct 06 '22 01:10

Joe Wilson


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.

like image 27
Baz1nga Avatar answered Oct 05 '22 23:10

Baz1nga