How to setup Request.Header in FakeHttpContext for Unit Testing
Asked Answered
G

3

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?
Granoff answered 18/6, 2015 at 8:15 Comment(2)
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.Chronic
I tried following the answers on this link #33140 but it seems not to work with WebAPI controllers but MVC controllersGranoff
G
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;
Granoff answered 18/6, 2015 at 12:32 Comment(3)
Property or indexer 'ControllerBase.Request' cannot be assigned to -- it is read only :-(Carminecarmita
Doesn't work in my caseFlawy
@OliverPearmain Microsoft changed the way WebAPI Controllers work in later versions and that's why it's not working. The solution is specifically for .Net 4.5 sorry that wasn't clear in the answer or post. learn.microsoft.com/en-us/dotnet/api/…Granoff
S
24

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/

Slideaction answered 10/11, 2020 at 20:40 Comment(5)
This one worked great for me, Controller.Request was readonly (.net cor 5) not sure if I missed something.Sentient
please provide the code for the setup of DefaultHttpContext classFlawy
It works like a charm ! thaks @DMendonzaPrivy
@ayushmishra The DefaultHttpContext class is part of the Microsoft.AspNetCore.Http namespace. Here's the link to Microsoft's documentation on it: DefaultHttpContext ClassSlideaction
Great solution for net core 3.1Lammergeier
G
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;
Granoff answered 18/6, 2015 at 12:32 Comment(3)
Property or indexer 'ControllerBase.Request' cannot be assigned to -- it is read only :-(Carminecarmita
Doesn't work in my caseFlawy
@OliverPearmain Microsoft changed the way WebAPI Controllers work in later versions and that's why it's not working. The solution is specifically for .Net 4.5 sorry that wasn't clear in the answer or post. learn.microsoft.com/en-us/dotnet/api/…Granoff
G
0

ControllerBase.Request is read only so it doesn't work for my case. I use Mock of IHttpContextAccessor and it works.

private readonly Mock<IHttpContextAccessor> _httpContext;
public UserAuthControllerTest()
{   
    _httpContext = new Mock<IHttpContextAccessor>();  
}

[Fact]
public async Task GetKey_Should_Return_Key()
{
    //Arrange
  _httpContext.Setup(expression: z => z.HttpContext.Request.Headers["publicKey"]).Returns(publicKey);

    //Act
    ...

    //Assert
    ...
}
Guipure answered 1/5 at 8:47 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.