18

I have a FakeHttpContext I have been trying to modify to include some headers for testing purposes

public static HttpContext FakeHttpContext()
{
    var httpRequest = new HttpRequest("", "http://stackoverflow/", "");
    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 });

    return httpContext;
 }

This works without the headers but when I add any of these lines of code in between the httpRequest and stringWriter lines.

    httpRequest.Headers.Add("blah", "1234");
    httpRequest.Headers["blah"] = "1234";

It throws

An exception of type 'System.PlatformNotSupportedException' occurred in System.Web.dll but was not handled in user code

  • Why am I getting that exception?
  • Is there a possible way to add headers to HttpContext for testing WebApi controllers?
Oluwafemi
  • 14,243
  • 11
  • 43
  • 59
  • If you can get your code to work with HttpContextBase, then you can usually mock things like this (including the request, and the request headers). Generally, that shouldn't be a problem as long as you aren't using HttpContext.Current. – Reddog Jun 18 '15 at 08:44
  • I tried following the answers on this link http://stackoverflow.com/questions/32640/mocking-asp-net-mvc-controller-context but it seems not to work with WebAPI controllers but MVC controllers – Oluwafemi Jun 18 '15 at 08:48

2 Answers2

22

I'm using .Net Core 3.1 and the Moq framework. I created a DefaultHttpContext, set the headers there, finally assigned it to the controller ControllerContext constructor.

var httpContext = new DefaultHttpContext();
httpContext.Request.Headers["X-Example"] = "test-header";
var controller = new ExampleController(mockClient.Object, mockLogger.Object) 
{ 
    ControllerContext = new ControllerContext()
    {
        HttpContext = httpContext
    }
};

Source: https://www.thecodebuzz.com/unit-test-mock-httprequest-in-asp-net-core-controller/

DMendoza
  • 412
  • 4
  • 8
  • 2
    This one worked great for me, Controller.Request was readonly (.net cor 5) not sure if I missed something. – John Irvine Aug 05 '21 at 23:47
  • please provide the code for the setup of DefaultHttpContext class – ayush mishra Oct 31 '21 at 05:52
  • 1
    It works like a charm ! thaks @DMendonza – m4verick Nov 04 '21 at 23:19
  • @ayushmishra The DefaultHttpContext class is part of the Microsoft.AspNetCore.Http namespace. Here's the link to Microsoft's documentation on it: [DefaultHttpContext Class](https://learn.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.http.defaulthttpcontext?view=aspnetcore-6.0) – DMendoza Dec 22 '21 at 19:02
  • 1
    Great solution for net core 3.1 – toha Sep 20 '22 at 08:38
14

I just discovered that with HttpRequestMessage class, you can easily add headers for testing your WebAPI controllers without having to create any fake HttpContext.

var request = new HttpRequestMessage(HttpMethod.Get, "http://stackoverflow");
request.Headers.Add("deviceId","1234");
_myController.Request = request;
Jesse
  • 3,522
  • 6
  • 25
  • 40
Oluwafemi
  • 14,243
  • 11
  • 43
  • 59