ASP.Net Core 6 SignInManager PasswordSignInAsync throws provider null exception
Is there an existing issue for this?
- [X] I have searched the existing issues
Describe the bug
SignInManager PasswordwordSignInAsync throws "Value cannot be null. (Parameter 'provider')" exception when I am unit-testing MVC Razor with ASP.Net Core 6 Identity.
var httpContextMock = new Mock<HttpContext>();
var httpContextAccessorMock = new Mock<IHttpContextAccessor>();
httpContextAccessorMock.Setup(x => x.HttpContext).Returns(httpContextMock.Object);
var httpContextMockObject = httpContextAccessorMock.Object;
IServiceCollection services = new ServiceCollection();
services.AddScoped(x => httpContextAccessorMock);
services.AddScoped(x => httpContextMockObject);
services.AddAuthentication();
services.AddScoped<SignInManager<MyUser>>();
What do I miss?
Expected Behavior
No error to build a unit test for Razor application.
Steps To Reproduce
No response
Exceptions (if any)
"Value cannot be null. (Parameter 'provider')"
.NET Version
6.0.9, 6.0.109
Anything else?
No response
The service provider needs to be set on the HttpContext:
httpContextMock.Setup(x => x.RequestServices).Returns(() => sp.CreateScope());
Assuming you build the service provider at some point.
System.ArgumentException : Invalid callback. Setup on method with return type 'IServiceProvider' cannot invoke callback with return type 'IServiceScope'.
httpContextMock.Setup(x => x.RequestServices).Returns(() => sp.CreateScope().ServiceProvider);
Now it crashes at:
at Microsoft.AspNetCore.Authentication.Cookies.CookieAuthenticationHandler.InitializeHandlerAsync()\n
at Microsoft.AspNetCore.Authentication.AuthenticationHandler`1.InitializeAsync(AuthenticationScheme scheme, HttpContext context)\n
at Microsoft.AspNetCore.Authentication.AuthenticationHandlerProvider.GetHandlerAsync(HttpContext context, String authenticationScheme)\n
at Duende.IdentityServer.Hosting.FederatedSignOut.FederatedSignoutAuthenticationHandlerProvider.GetHandlerAsync(HttpContext context, String authenticationScheme) in /_/src/IdentityServer/Hosting/FederatedSignOut/FederatedSignoutAuthenticationHandlerProvider.cs:line 33\n
at Duende.IdentityServer.Services.DefaultUserSession.AuthenticateAsync() in /_/src/IdentityServer/Services/Default/DefaultUserSession.cs:line 137\n
at Duende.IdentityServer.Services.DefaultUserSession.GetUserAsync() in /_/src/IdentityServer/Services/Default/DefaultUserSession.cs:line 204\n
at Duende.IdentityServer.Services.DefaultUserSession.CreateSessionIdAsync(ClaimsPrincipal principal, AuthenticationProperties properties) in /_/src/IdentityServer/Services/Default/DefaultUserSession.cs:line 168\n
at Duende.IdentityServer.Hosting.IdentityServerAuthenticationService.SignInAsync(HttpContext context, String scheme, ClaimsPrincipal principal, AuthenticationProperties properties) in /_/src/IdentityServer/Hosting/IdentityServerAuthenticationService.cs:line 59\n
at Microsoft.AspNetCore.Identity.SignInManager`1.SignInWithClaimsAsync(TUser user, AuthenticationProperties authenticationProperties, IEnumerable`1 additionalClaims)\n
at Microsoft.AspNetCore.Identity.SignInManager`1.SignInOrTwoFactorAsync(TUser user, Boolean isPersistent, String loginProvider, Boolean bypassTwoFactor)\n
at Microsoft.AspNetCore.Identity.SignInManager`1.PasswordSignInAsync(TUser user, String password, Boolean isPersistent, Boolean lockoutOnFailure)\n
at Microsoft.AspNetCore.Identity.SignInManager`1.PasswordSignInAsync(String userName, String password, Boolean isPersistent, Boolean lockoutOnFailure)\n
at KyberlifeIAM.Infrastructure.Data.Repositories.UserRepository.SignIn(String username, String password, String remoteIP, Boolean rememberMe, Boolean logoutOnFailure) in /usr/src/kyberlife/KyberlifeIAM/src/KyberlifeIAM.Infrastructure/Data/Repositories/UserRepository.cs:line 216"
Have you set up the HttpResponse on your mocked HttpContext?
https://github.com/dotnet/aspnetcore/blob/f96dce6889fe67aaed33f0c2b147b8b537358f1e/src/Security/Authentication/Cookies/src/CookieAuthenticationHandler.cs#L61
You're going to have to work through the code and set up your mock with the appropriate properties/services/method results that are expected at runtime.
Alternatively, look into another approach to testing with integration tests where you won't have to worry about setting up mocks (and thus implementation details) so specifically and precisely to make your tests work.
Thank you for contacting us. Due to a lack of activity on this discussion issue we're closing it in an effort to keep our backlog clean. If you believe there is a concern related to the ASP.NET Core framework, which hasn't been addressed yet, please file a new issue.
This issue will be locked after 30 more days of inactivity. If you still wish to discuss this subject after then, please create a new issue!