In ASP.NET Core unit tests, if you want to mock HttpContext.Features.Get<SomeType>(), here's the trick.


I have my Error page code that will get exception detail infomation, to do that, I use HttpContext.Features.Get<IExceptionHandlerPathFeature>().

public void OnGet()
    var requestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier;
    var exceptionFeature = HttpContext.Features.Get<IExceptionHandlerPathFeature>();
    if (exceptionFeature is not null)
        // Get which route the exception occurred at
        var routeWhereExceptionOccurred = exceptionFeature.Path;

        // Get the exception that occurred
        var exceptionThatOccurred = exceptionFeature.Error;
        _logger.LogError($"Error: {routeWhereExceptionOccurred}, " +
                         $"client IP: {HttpContext.Connection.RemoteIpAddress}, " +
                         $"request id: {requestId}", exceptionThatOccurred);

    RequestId = requestId;

Now I want to unit test this piece of code. Usually I will use DefaultHttpContext instance in unit tests that requires an HttpContext for a page or controller. But I found the Features property is readonly on the HttpContext class. So there's no way to assign values that we mocked to this property.

namespace Microsoft.AspNetCore.Http
    public abstract class HttpContext
        protected HttpContext();

        // Summary:
        //     Gets the collection of HTTP features provided by the server and middleware available
        //     on this request.
        public abstract IFeatureCollection Features { get; }
        //  ...


First, prepare the mock as usual. In my case, I set up IFeatureCollection.Get() method to return my desired object.

var mockIFeatureCollection = _mockRepository.Create<IFeatureCollection>();
mockIFeatureCollection.Setup(p => p.Get<IExceptionHandlerPathFeature>())
    .Returns(new ExceptionHandlerFeature
        Path = "/996/icu",
        Error = new("Too much fubao")
httpContextMock.Setup(p => p.Features).Returns(mockIFeatureCollection.Object);

Then, in order to assign values to HttpContext.Features, we can't use DefaultHttpContext this time. We have to create a mock for HttpContext. And set up the Features property to return our mocked IFeatureCollection object.

var httpContextMock = _mockRepository.Create<HttpContext>();
httpContextMock.Setup(p => p.Features).Returns(mockIFeatureCollection.Object);

Now, run the unit test, we can see values are coming up correctly.