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.
If your controller need authentication info from HttpContext, I would:
- 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.
- In the methods/properties in AuthenticationService, call into the real HttpContext, like HttpContext.Current.user.Identity.Name.
- Create an interface over the new AuthenticationService with the public methods/properties you care about.
- 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.
- 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.
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.
精彩评论