HttpContextAccessor returns null for HttpContext in tests
I want to add some EF Core query filters inside my DbContext's OnModelCreating that ultimately leverage values from the user's ClaimsPrincipal, so I need to access the HttpContext for the request to grab it from that. Injecting IHttpContextAccessor into DbContext (long term I'd probably inject a TenantService instead) works when the app is run normally, but when running integration tests with WebApplicationFactory HttpContext always seems to be null.
Not sure if I'm missing something in my test setup or if my approach is wrong to begin with, but here's a contrived example: https://github.com/mwojtul/todos/blob/context-accessor/TodoApi/Data/AppDbContext.cs
If I run this app normally it'll work as expected and the /api/todos endpoint will always return an empty list, but my test suite that endpoint will return a todo
10 Replies
coupling your database with anything related to HTTP seems extremely suspicious
would you just not use query filters then?
if all you need are the claims you're making it pull in more than it actually needs
i don't use query filters in any projects right now and i don't know your goals so i can't answer that, but i do have an audit log interceptor that needs user information
and for that i have a separate service so the database doesn't need to know where the user information came from
fwiw, i have the same problem if i inject a separate service into the dbcontext. httpcontext when accessed in that service will be null
but you wouldn't have a httpcontext in a unit test to begin with
you'd mock in something that gives you fake values to test against
i thought you would when using HttpClient to send a request
are you writing a unit test or an integration test?
integration
do you have an example of a test you're trying to write?
https://github.com/mwojtul/todos/blob/context-accessor/TodoApi.Tests/Integration/TodoEndpointsTests.cs#L12 here's the test
it seems like in tests the HttpContextAccessor runs at startup and HttpContext is of course null, but when a request is made, it doesn't rerun. on the other hand when running the app, it doesn't run at startup but does run when a request is made
okay, so the fix was that i need to only access contextAccessor.HttpContext inside the lambda of HasQueryFilter so that the check is deferred until a request is made. wrapping the HasQueryFilter in an if statement is probably weird to begin with but worked during app execution but not during test runs, must be some minor difference with how the app is ran with WebApplicationFactory