Mocking HttpContextBase with Moq

前端 未结 2 1591
悲哀的现实
悲哀的现实 2020-11-27 16:04

I have a unit test fixture in which I\'m trying to test a ControllerAction on an ASP.NET MVC controller that\'s used for membership functions on a web app. I\'m trying to mo

相关标签:
2条回答
  • 2020-11-27 16:46

    Here's how I do it.

        public static HttpContextBase FakeHttpContext()
        {
            var context = new Mock<HttpContextBase>();
            var request = new Mock<HttpRequestBase>();
            var response = new Mock<HttpResponseBase>();
            var session = new Mock<HttpSessionStateBase>();
            var server = new Mock<HttpServerUtilityBase>();
            var user = new Mock<IPrincipal>();
            var identity = new Mock<IIdentity>();
    
            request.Expect(req => req.ApplicationPath).Returns("~/");
            request.Expect(req => req.AppRelativeCurrentExecutionFilePath).Returns("~/");
            request.Expect(req => req.PathInfo).Returns(string.Empty);
            response.Expect(res => res.ApplyAppPathModifier(It.IsAny<string>()))
                .Returns((string virtualPath) => virtualPath);
            user.Expect(usr => usr.Identity).Returns(identity.Object);
            identity.ExpectGet(ident => ident.IsAuthenticated).Returns(true);
    
            context.Expect(ctx => ctx.Request).Returns(request.Object);
            context.Expect(ctx => ctx.Response).Returns(response.Object);
            context.Expect(ctx => ctx.Session).Returns(session.Object);
            context.Expect(ctx => ctx.Server).Returns(server.Object);
            context.Expect(ctx => ctx.User).Returns(user.Object);
    
            return context.Object;
        }
    

    This is an enhanced version of the MvcMockHelpers library released by Scott Hanselman. This is Moq 2.0 code; the syntax is slightly different in 3.

    0 讨论(0)
  • 2020-11-27 16:50

    I'm using a version of some code Steve Sanderson included in his Pro Asp.NET MVC book... and I'm currently having a moral dilemma whether it's okay to post the code here. How about I compromise with a highly stripped down version? ;)

    So this can easily be reused, create a class similar to the one below that you will pass your controller. This will set up your mocks and set them to your controller's ControllerContext

    public class ContextMocks
    {
        public Moq.Mock<HttpContextBase> HttpContext { get; set; }
        public Moq.Mock<HttpRequestBase> Request { get; set; }
        public RouteData RouteData { get; set; }
    
        public ContextMocks(Controller controller)
        {
            //define context objects
            HttpContext = new Moq.Mock<HttpContextBase>();
            HttpContext.Setup(x => x.Request).Returns(Request.Object);
            //you would setup Response, Session, etc similarly with either mocks or fakes
    
            //apply context to controller
            RequestContext rc = new RequestContext(HttpContext.Object, new RouteData());
            controller.ControllerContext = new ControllerContext(rc, controller);
        }
    }
    

    And then in your test method you'd just create an instance of ContextMocks and pass in the controller object you're testing:

    [Test]
    Public void test()
    {
         var mocks = new ContextMocks(controller);
         var req = controller.Request; 
         //do some asserts on Request object
    }
    

    Seems very similar to Craig's examples, but this is with Moq v3. I have to give props to Steve Sanderson for this - I'm using this as a basis for testing all kinds of otherwise traditionally hard-to-test stuff: cookies, session, request method, querystring and more!

    0 讨论(0)
提交回复
热议问题