Mock IHttpContextAccessor in Unit Tests
28,313
In my scenario I had to mock IHttpContextAccessor
and access the inner request url bits.
I'm sharing it here because I spent a decent amount of time figuring this out and hopefully it'll help someone.
readonly Mock<IHttpContextAccessor> _HttpContextAccessor =
new Mock<IHttpContextAccessor>(MockBehavior.Strict);
void SetupHttpContextAccessorWithUrl(string currentUrl)
{
var httpContext = new DefaultHttpContext();
setRequestUrl(httpContext.Request, currentUrl);
_HttpContextAccessor
.SetupGet(accessor => accessor.HttpContext)
.Returns(httpContext);
static void setRequestUrl(HttpRequest httpRequest, string url)
{
UriHelper
.FromAbsolute(url, out var scheme, out var host, out var path, out var query,
fragment: out var _);
httpRequest.Scheme = scheme;
httpRequest.Host = host;
httpRequest.Path = path;
httpRequest.QueryString = query;
}
}
Author by
superninja
Updated on July 08, 2022Comments
-
superninja almost 2 years
I have a method to get header value using
IHttpContextAccessor
public class HeaderConfiguration : IHeaderConfiguration { public HeaderConfiguration() { } public string GetTenantId(IHttpContextAccessor httpContextAccessor) { return httpContextAccessor.HttpContext.Request.Headers["Tenant-ID"].ToString(); } }
I am testing
GetBookByBookId
methodLet's say the method looks like this:
public class Book { private readonly IHttpContextAccessor _httpContextAccessor; private IHeaderConfiguration _headerConfiguration; private string _tenantID; public Book(IHeaderConfiguration headerConfiguration, IHttpContextAccessor httpContextAccessor){ var headerConfig = new HeaderConfiguration(); _httpContextAccessor = httpContextAccessor; _tenantID = headerConfig.GetTenantId(_httpContextAccessor); } public Task<List<BookModel>> GetBookByBookId(string id){ //do something with the _tenantId //... } }
Here's my unit test for
GetBookByBookId
method[Fact] public void test_GetBookByBookId() { //Arrange //Mock IHttpContextAccessor var mockHttpContextAccessor = new Mock<IHttpContextAccessor>(); mockHttpContextAccessor.Setup(req => req.HttpContext.Request.Headers["Tenant-ID"].ToString()).Returns(It.IsAny<string>()); //Mock HeaderConfiguration var mockHeaderConfiguration = new Mock<IHeaderConfiguration>(); mockHeaderConfiguration.Setup(x => x.GetTenantId(mockHttpContextAccessor.Object)).Returns(It.IsAny<string>()); var book = new Book( mockHttpContextAccessor.Object, mockHeaderConfiguration.Object); var bookId = "100"; //Act var result = book.GetBookByBookId(bookId); //Assert result.Result.Should().NotBeNull().And. BeOfType<List<BookModel>>(); }
But for this line:
mockHttpContextAccessor.Setup(req => req.HttpContext.Request.Headers["Tenant-ID"].ToString()).Returns(It.IsAny<string>());
It says
System.NotSupportedException: 'Type to mock must be an interface or an abstract or non-sealed class. '
I was wondering what's the proper way to mock
IHttpContextAccessor
with header value? -
Shimmy Weitzhandler over 3 years
_HttpContextAccessor.SetupGet(accessor => accessor.HttpContext).Returns(httpContext);