0

I found this code for doing a mock request for the purposes of unit testing. I'm trying to set the userhostaddress but I'm not clear how to use the same method outlined in this code to achieve that. I'm thinking it has to be done through reflection as I'm finding setting the headers is not allowed. Any ideas how I can achieve this?

public static HttpContext FakeHttpContext()
        {
            var httpRequest = new HttpRequest("", "http://fakurl/", "");
            var stringWriter = new StringWriter();
            var httpResponse = new HttpResponse(stringWriter);
            var httpContext = new HttpContext(httpRequest, httpResponse);

            var sessionContainer = new HttpSessionStateContainer("id", new SessionStateItemCollection(),
                                                    new HttpStaticObjectsCollection(), 10, true,
                                                    HttpCookieMode.AutoDetect,
                                                    SessionStateMode.InProc, false);

            httpContext.Items["AspSession"] = typeof(HttpSessionState).GetConstructor(
                                        BindingFlags.NonPublic | BindingFlags.Instance,
                                        null, CallingConventions.Standard,
                                        new[] { typeof(HttpSessionStateContainer) },
                                        null)
                                .Invoke(new object[] { sessionContainer });

            httpContext.Request.Headers["REMOTE_ADDR"] = "XXX.XXX.XXX.XXX"; // not allowed
            return httpContext;
        }

I also tried this mocking library:

https://gist.github.com/rally25rs/1578697

By the user host address is still readonly.

KingOfHypocrites
  • 9,316
  • 9
  • 47
  • 69
  • Found this which shows how to do it: http://stackoverflow.com/questions/13157101/how-to-set-the-ip-userhostaddress-on-a-mocked-basehttpcontext – KingOfHypocrites Nov 07 '13 at 20:15

1 Answers1

0

Best approach I've found is to have some sort of ContextService that implements an IContextService interface. This class/interface pair can do whatever operations you need it to. Point is, if you use a mocking framework in your unit tests like MOQ then you can wire up a mock context service to return a particular ip address.

This StackOverflow post has some good pointers: Moq: unit testing a method relying on HttpContext.

UPDATE:

The StackOverflow post you found is also a good one: How to set the IP (UserHostAddress) on a "mocked' BaseHttpContext?

I find that often I'll only need a few properties off of the context/request/response objects, so I often roll my own smaller variant:

public class ContextService : IContextService
{
    public string GetUserHostAddress()
    {
        return HttpContext.Current.Request.UserHostAddress;
    }
}
public interface IContextService
{
    string GetUserHostAddress();
}

With that class/interface combo, I can then use Moq to wire up a fake service:

var contextMock = new Moq.Mock<IContextService>();
contextMock.Setup(c => c.GetUserHostAddress()).Returns("127.0.0.1");

Now every time I call contextMock.GetUserHostAddress(), I'll get "127.0.0.1". Rolling your own can be a great learning experience, especially if you don't need all the bells and whistles of a full-blown (or as full as possible anyway) HttpContext mock.

Community
  • 1
  • 1
Brian Oliver
  • 1,407
  • 2
  • 15
  • 25
  • I found this but not sure where to set it in the controller. THe httpcontext is read only. https://gist.github.com/frankshearar/837741 >> var requestContext = MvcMockHelpers.FakeHttpContext(); – KingOfHypocrites Nov 07 '13 at 19:56
  • I think I found a way to pass it to the controller, but the userhostname is still readonly so doesn't do me any good: httpContext.Request.UserHostAddress= "127.0.0.1"; – KingOfHypocrites Nov 07 '13 at 20:01
  • 1
    Found this which shows how to do it: http://stackoverflow.com/questions/13157101/how-to-set-the-ip-userhostaddress-on-a-mocked-basehttpcontext – KingOfHypocrites Nov 07 '13 at 20:16