ASP.Net Core 2.0 SignInAsync returns exception Value cannot be null, provider

I have an ASP.Net Core 2.0 web application I am retrofitting with unit tests (using NUnit). The application works fine, and most of the tests thus far work fine.

However, testing the authentication/authorization (does a user get logged in and can access [Authorize] filtered actions) is failing with...

System.ArgumentNullException: Value cannot be null.
Parameter name: provider

...after...

await HttpContext.SignInAsync(principal);

...but it is not clear what in fact is the underlying cause. Code execution stops in the called method here and no exception is shown in the IDE but code execution returns to the caller, then terminates (yet I still see The program '[13704] dotnet.exe' has exited with code 0 (0x0). in the output window of VS.)

The Test Explorer shows red and gives the exception referenced (otherwise I would have no idea as to the problem.)

I am working on creating a repro to point folks to (turning out to bit a bit involved thus far.)

Does anyone know how to pinpoint the underlying cause? Is this a DI related issue (something needed that isn't being provided in the test but is in normal execution)?

UPDATE1: Providing requested authentication code...

public async Task<IActionResult> Registration(RegistrationViewModel vm) {
    if (ModelState.IsValid) {
        // Create registration for user
        var regData = createRegistrationData(vm);
        _repository.AddUserRegistrationWithGroup(regData);

        var claims = new List<Claim> {
            new Claim(ClaimTypes.NameIdentifier, regData.UserId.ToString())
        };
        var ident = new ClaimsIdentity(claims);
        var principal = new ClaimsPrincipal(ident);

        await HttpContext.SignInAsync(principal); // FAILS HERE

        return RedirectToAction("Welcome", "App");
    } else {
        ModelState.AddModelError("", "Invalid registration information.");
    }

    return View();
}

The test code that fails...

public async Task TestRegistration()
{
    var ctx = Utils.GetInMemContext();
    Utils.LoadJsonData(ctx);
    var repo = new Repository(ctx);
    var auth = new AuthController(repo);
    auth.ControllerContext = new ControllerContext();
    auth.ControllerContext.HttpContext = new DefaultHttpContext();

    var vm = new RegistrationViewModel()
    {
        OrgName = "Dev Org",
        BirthdayDay = 1,
        BirthdayMonth = "January",
        BirthdayYear = 1979 
    };

    var orig = ctx.Registrations.Count();
    var result = await auth.Registration(vm); // STEPS IN, THEN FAILS
    var cnt = ctx.Registrations.Count();
    var view = result as ViewResult;

    Assert.AreEqual(0, orig);
    Assert.AreEqual(1, cnt);
    Assert.IsNotNull(result);
    Assert.IsNotNull(view);
    Assert.IsNotNull(view.Model);
    Assert.IsTrue(string.IsNullOrEmpty(view.ViewName) || view.ViewName == "Welcome");
}

UPDATE3: Based on chat @nkosi suggested that this is a problem stemming from my not fulfilling the needs of the dependency injection requirements for HttpContext.

However, what isn't yet clear is: if it is, in fact, an issue of not providing the proper service dependency, why does the code work normally (when not being tested). The SUT (controller) only accepts an IRepository parameter (so that is all that is provided in any case.) Why create an overloaded ctor (or mock) just for test, when the existing ctor is all that is called when running the program and it runs without issue?

UPDATE4: While @Nkosi answered the bug/problem with a solution, I am still wondering why the IDE isn't accurately/consistently presenting the underlying exception. Is this a bug, or due to the async/await operators and the NUnit Test Adapter/runner? Why aren't exceptions "popping" like I would expect while debugging the test, and the exit code is still zero (typically indicating a successful return state)?

What isn't yet clear is: if it is, in fact, an issue of not providing the proper service dependency, why does the code work normally (when not being tested). The SUT (controller) only accepts an IRepository parameter (so that is all that is provided in any case.) Why create an overloaded ctor (or mock) just for test, when the existing ctor is all that is called when running the program and it runs without issue?

You are mixing up a few things here: First of all, you don’t need to create separate constructors. Not for testing, and not for actually running this as part of your application.

You should define all the direct dependencies your controller has as parameters to the constructor, so that when this runs as part of the application, the dependency injection container will provide those dependencies to the controller.

But that’s also the important bit here: When running your application, there is a dependency injection container that is responsible of creating objects and providing the required dependencies. So you actually don’t need to worry too much about where they come from. This is different when unit testing though. In unit tests, we don’t want to use dependency injection since that will just hide dependencies, and as such possible side effects that may conflict with our test. Relying on dependency injection within a unit test is a very good sign that you are not unit testing but doing an integration test instead (at least unless you are actually testing a DI container).

Instead, in unit tests, we want to create all objects explicitly providing all dependencies explicitly. This means that we new up the controller and pass all dependencies the controller has. Ideally, we use mocks so we don’t depend on external behavior in our unit test.

This is all pretty straight forward most of the time. Unfortunately, there is something special about controllers: Controllers have a ControllerContext property that is automatically provided during the MVC lifecycle. Some other components within MVC have similar things (e.g. the ViewContext is also automatically provided). These properties are not constructor injected, so the dependency is not explicitly visible. Depending on what the controller does, you might need to set these properties too when unit testing the controller.


Coming to your unit test, you are using HttpContext.SignInAsync(principal) inside your controller action, so unfortunately, you are operating with the HttpContext directly.

SignInAsync is an extension method which will basically do the following:

context.RequestServices.GetRequiredService<IAuthenticationService>().SignInAsync(context, scheme, principal, properties);

So this method, for pure convenience, will use the service locator pattern to retrieve a service from the dependency injection container to perform the sign-in. So just this one method call on the HttpContext will pull in further implicit dependencies that you only discover about when your test fails. That should serve as a good example on why you should avoid the service locator pattern: Explicit dependencies in the constructor are much more manageable. – But here, this is a convenience method, so we will have to live with that and just adjust the test to work with this.

Actually, before moving on, I want to mention a good alternative solution here: Since the controller is a AuthController I can only imagine that one of its core purposes is to do authentication stuff, signing users in and out and things. So it might actually be a good idea not to use HttpContext.SignInAsync but instead have the IAuthenticationService as an explicit dependency on the controller, and calling the methods on it directly. That way, you have a clear dependency that you can fulfill in your tests and you don’t need to get involved with the service locator.

Of course, this would be a special case for this controller and won’t work for every possible call of the extension methods on the HttpContext. So let’s tackle how we can test this properly:

As we can see from the code what SignInAsync actually does, we need to provide a IServiceProvider for HttpContext.RequestServices and make that be able to return an IAuthenticationService. So we’ll mock these:

var authenticationServiceMock = new Mock<IAuthenticationService>();
authenticationServiceMock
    .Setup(a => a.SignInAsync(It.IsAny<HttpContext>(), It.IsAny<string>(), It.IsAny<ClaimsPrincipal>(), It.IsAny<AuthenticationProperties>()))
    .Returns(Task.CompletedTask);

var serviceProviderMock = new Mock<IServiceProvider>();
serviceProviderMock
    .Setup(s => s.GetService(typeof(IAuthenticationService)))
    .Returns(authenticationServiceMock.Object);

Then, we can pass that service provider in the ControllerContext after creating the controller:

var controller = new AuthController();
controller.ControllerContext = new ControllerContext
{
    HttpContext = new DefaultHttpContext()
    {
        RequestServices = serviceProviderMock.Object
    }
};

That’s all we need to do to make HttpContext.SignInAsync work.

Unfortunately, there is a bit more to it. As I’ve explained in this other answer (which you already found), returning a RedirectToActionResult from a controller will cause problems when you have the RequestServices set up in a unit test. Since RequestServices are not null, the implementation of RedirectToAction will attempt to resolve an IUrlHelperFactory, and that result has to be non-null. As such, we need to expand our mocks a bit to also provide that one:

var urlHelperFactory = new Mock<IUrlHelperFactory>();
serviceProviderMock
    .Setup(s => s.GetService(typeof(IUrlHelperFactory)))
    .Returns(urlHelperFactory.Object);

Luckily, we don’t need to do anything else, and we also don’t need to add any logic to the factory mock. It’s enough if it’s just there.

So with this, we can test the controller action properly:

// mock setup, as above
// …

// arrange
var controller = new AuthController(repositoryMock.Object);
controller.ControllerContext = new ControllerContext
{
    HttpContext = new DefaultHttpContext()
    {
        RequestServices = serviceProviderMock.Object
    }
};

var registrationVm = new RegistrationViewModel();

// act
var result = await controller.Registration(registrationVm);

// assert
var redirectResult = result as RedirectToActionResult;
Assert.NotNull(redirectResult);
Assert.Equal("Welcome", redirectResult.ActionName);

I am still wondering why the IDE isn't accurately/consistently presenting the underlying exception. Is this a bug, or due to the async/await operators and the NUnit Test Adapter/runner?

I have seen something similar in the past too with my asynchronous tests, that I could not debug them properly or that exceptions wouldn’t be displayed correctly. I don’t remember seeing this in recent versions of Visual Studio and xUnit (I’m personally using xUnit, not NUnit). If it helps, running the tests from the command line with dotnet test will usually work properly and you will get proper (async) stack traces for failures.

ASP.NET Core provides the web app development features used by . Identity: SignInAsync throws exception for unauthenticated identity Logging uses the integer values of HTTP status codes. NET Core 2.0 added initial support for SameSite . OAuthCodeExchangeContext context) { throw null; }  Browse other questions tagged c# unit-testing asp.net-core.net-core asp.net-core-2.0 or ask your own question. The Overflow Blog The Overflow #21: The way forward

Is this a DI related issue (something needed that isn't being provided in the test but is in normal execution)?

YES

You are calling features that the framework would setup for you at run time. During isolated unit tests you will need to set these up yourself.

The Controller's HttpContext is missing an IServiceProvider which it uses to resolve IAuthenticationService. That service is what actually calls SignInAsync

In order to let....

await HttpContext.SignInAsync(principal);  // FAILS HERE

...in the Registration action to execute to completion during the unit test you will need to mock a service provider so that the SignInAsync extension method does not fail.

Update the unit test arrangement

//...code removed for brevity

auth.ControllerContext.HttpContext = new DefaultHttpContext() {
    RequestServices = createServiceProviderMock()
};

//...code removed for brevity

Where createServiceProviderMock() is a small method used to mock a service provider that will be used to populate the HttpContext.RequestServices

public IServiceProvider createServiceProviderMock() {
    var authServiceMock = new Mock<IAuthenticationService>();
    authServiceMock
        .Setup(_ => _.SignInAsync(It.IsAny<HttpContext>(), It.IsAny<string>(), It.IsAny<ClaimsPrincipal>(), It.IsAny<AuthenticationProperties>()))
        .Returns(Task.FromResult((object)null)); //<-- to allow async call to continue

    var serviceProviderMock = new Mock<IServiceProvider>();
    serviceProviderMock
        .Setup(_ => _.GetService(typeof(IAuthenticationService)))
        .Returns(authServiceMock.Object);

    return serviceProviderMock.Object;
}

I would also suggest mocking the Repository for the purposes of an isolated unit test of that controller action to make sure it flows to completion without any negative effects

Tag Archives: ArgumentNullException: Value cannot be null. 5. 6. 7. 8. 9. 10. 11. 12. using Microsoft.AspNetCore.Identity. return Task. SignInAsync(user, isPersistent: false ); PopulateCallSites(ServiceProvider provider, ISet callSiteChain, ParameterInfo[] parameters, bool throwIfCallSiteNotFound). Entity Framework Core 2.0.1-rtm-125 initialized 'ApplicationDbContext' using provider 'Microsoft.EntityFrameworkCore.SqlServer' with options: MigrationsAssembly=Project.Data System.ArgumentNullException: Value cannot be null.

as @poke mentioned you better not use Dependency Injection in unit tests and provide dependencies explicitly (using mocking) but however, I had this issue in my integration tests and I figured that the problem arises from RequestServices property of HttpContext which is not properly initialized in tests (since we don't use actual HttpContext in tests) so I registered my HttpContextAccessor like below and passed all of it's required service myself (manually) and problem solved. see code below

Services.AddSingleton<IHttpContextAccessor>(new HttpContextAccessor() { HttpContext = new DefaultHttpContext() { RequestServices = Services.BuildServiceProvider() } });

I agree it's not a very clean solution but note that I wrote and used this code only in my tests in order to provide required HttContext dependencies (which were not supplied automatically in test method), in your application IHttpContextAccessor, HttpContext and their required services are automatically provided by framework.

here is all of my dependency registration method in my tests base class constructor

 public class MyTestBaseClass
 {
  protected ServiceCollection Services { get; set; } = new ServiceCollection();
  MyTestBaseClass
 {

   Services.AddDigiTebFrameworkServices();
        Services.AddDigiTebDBContextService<DigiTebDBContext> 
        (Consts.MainDBConnectionName);
        Services.AddDigiTebIdentityService<User, Role, DigiTebDBContext>();
        Services.AddDigiTebAuthServices();
        Services.AddDigiTebCoreServices();
        Services.AddSingleton<IHttpContextAccessor>(new HttpContextAccessor() { HttpContext = new DefaultHttpContext() { RequestServices = Services.BuildServiceProvider() } });
}
}

Part 4: OAuth 2.0, OpenID Connect & IdentityServer; Part 5: External Provider authentication & registration strategy; Part 6: Two-Factor  After calling SignInAsync, the IsAuthenticated function still returns false. This is a regression from ASP.NET Core 2 Preview 1 in which the same code worked as expected. Repro: New project: dotnet --version 2.0.0-preview2-006497 dotnet new mvc Add in startup.cs:

ASP.NET Core 2.0 provides various ways of implementing cookie-based going to discuss on using cookie authentication as standalone authentication provider in an ASP. containing the isValid value and the user, if isValid is true, else a null value. Lastly, I return a Task , which is required from the method's signature. ASP.Net Core 2.0 SignInAsync returns exception Value cannot be null, provider Value cannot be null. Parameter name: provider Authorization in ASP.NET Core 2.0

Click here to return to Amazon Web Services homepage NET Core Identity Provider for Amazon Cognito, which enables ASP. NET Standard 2.0, the custom ASP. Task<IActionResult> OnPostAsync(string returnUrl = null) { returnUrl SignInAsync(user, isPersistent: false); // Redirects to the account  In 2.0 If i do override the option.DefaultSignInScheme = CookieAuthenticationDefaults.AuthenticationScheme; the HttpContext.User is null after the HttpContext.SiginAsync (but not null after a new http request), e.g in this case user is null.

16 ASP.Net Core 2.0 SignInAsync returns exception Value cannot be null, provider · 10 asp5 IConfigurationRoot get json array · 5 ef7 unable to retrieve child  ASP.NET CORE Web API: Value are always null when doing HTTP Post requests. #2202. lorenz31 opened this issue on Sep 18, 2017 · 46 comments. lorenz31 commented on Sep 18, 2017 • I'm experiencing a problem doing post requests via ASP.NET Core Web API. I'm a bit confused of the articles I read/found while Googling. So here's my scenario:

Comments
  • Can you show the code for authentication method? Also are you injecting the provider in the code? If so how have you setup your dummy injection in test?
  • @Aeseir - updated original post
  • Consider abstracting the sign in call out so as to be able to mock it when testing in isolation.
  • @Nkosi - Certainly worth consideration. I (don't yet) think that portion is necessary to isolate and understand the primary focus of my question though (correct?) That being: why is it breaking, and why is it being reported/reflected inconsistently.
  • @t.j. note that the docs are not accessing/calling the same members that you are using. You are calling features that the framework would setup for you at run time. During isolated unit tests you will need to set these up yourself. In this case you will need to mock the service provider so that the extension method does not fail.
  • Thank you so VERY much! What an excellent job of describing the nature of the problem, and solution! Someone advised elsewhere that I create another ctor to facilitate injecting the signin manager (which then caused further confusion and made little sense). The first param of IAuthenticationService is an HttpContext (which I would then have to inject anyways for tests)
  • Brief question: I am using sqlite in-mem provider for the repo during unit tests (so it is sql like, but easily disposable.) That is sufficient regarding your "mocking the Repository" statement, correct?
  • Ah! I see too now (as you stated) where I certainly setting the HttpContext in my test (and therefore, since I didn't provide it, wasn't getting all the needed services/dependencies met.)
  • Well explained, and well illustrated. Thank you so very much!
  • PS: There are more (related) problems to solve, but this got me headed in the needed direction.