ASP.NET Core Integration Test works locally but throws null reference exception when running in production environmentAsp.Net Core Challenge returns Null URI Exception errorHow to fix 500 Internal Server Error for POST integration tests using TestServer and Antiforgery? ASP.NET Coreasp.net mvc application throw controller exception when application is deployedAn exception of type 'System.Reflection.TargetInvocationException' occurred in mscorlib.dll but was not handled in user codeASP.Net Core Integration TestingUnity Dependency injection automatically expires after a particular time.. Why?Dependency injection in ASP.NET Core 2 throws exceptionError occurred when trying to create a controller of type 'EmployeeController'. Make sure controller has a parameterless public constructorASP.NET Core running two TestServer for Integration TestingMocking ODataQueryOptions on .Net CoreAfter retargeting to .NET Core 2.1 getting new error System.ObjectDisposedException: Cannot access a disposed objectThe reference to external elements from the source named 'xyz.dacpac' could not be resolved

Axiom of Choice in General Topology

How do I write real-world stories separate from my country of origin?

Were there any developed countries that became "undeveloped" for reasons other than war?

Why is the Psionic Artificer considered to be better than all other tier 1 classes?

Is there a word for pant sleeves?

Expand a hexagon

Must every right-inverse of a linear transformation be a linear transformation?

What is the required burn to keep a satellite at a Lagrangian point?

can conjure barrage stack with martial adept- disarming or tripping attack?

Can diplomats be allowed on the flight deck of a commercial European airline?

Why is 'additive' EQ more difficult to use than 'subtractive'?

Nunc est bibendum: gerund or gerundive?

What defines a person who is circumcised "of the heart"?

What to call a small, open stone or cement reservoir that supplies fresh water from a spring or other natural source?

How could the B-29 bomber back up under its own power?

How to remove unwanted horizontal line from diagbox

Managing heat dissipation in a magic wand

Results relying on higher derived algebraic geometry

Island Perimeter

Are there historical examples of audiences drawn to a work that was "so bad it's good"?

Coloring lines in a graph the same color if they are the same length

Make the `diff` command look only for differences from a specified range of lines

Ribbon Cable Cross Talk - Is there a fix after the fact?

Why "strap-on" boosters, and how do other people say it?



ASP.NET Core Integration Test works locally but throws null reference exception when running in production environment


Asp.Net Core Challenge returns Null URI Exception errorHow to fix 500 Internal Server Error for POST integration tests using TestServer and Antiforgery? ASP.NET Coreasp.net mvc application throw controller exception when application is deployedAn exception of type 'System.Reflection.TargetInvocationException' occurred in mscorlib.dll but was not handled in user codeASP.Net Core Integration TestingUnity Dependency injection automatically expires after a particular time.. Why?Dependency injection in ASP.NET Core 2 throws exceptionError occurred when trying to create a controller of type 'EmployeeController'. Make sure controller has a parameterless public constructorASP.NET Core running two TestServer for Integration TestingMocking ODataQueryOptions on .Net CoreAfter retargeting to .NET Core 2.1 getting new error System.ObjectDisposedException: Cannot access a disposed objectThe reference to external elements from the source named 'xyz.dacpac' could not be resolved






.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty height:90px;width:728px;box-sizing:border-box;








4















I have an ASP.NET Core 2.2 Razor Pages Web App that I have written some integration tests for following the official guide.



I can get the tests to run locally using dotnet test or the test runners built into Visual Studio. However, on the build server (Azure DevOps Hosted 2017 agent) the tests will return a 500 error. I thought it might be related to user secrets as stated on Scott Hanselman's guide but I am still getting the same error, even after implementing some of his suggested fixes (I don't believe I need all of them) :



  • Added builder.AddUserSecrets<Startup>(); to Startup.

  • Implemented a CustomWebApplicationFactory to set the environment to "Development" - code below has this as "Production" to reproduce the failure.

I also sanity checked against this guide which is more controller focused but since I only care about the response codes at this stage it serves my purpose. I have downloaded the verbose logs and they don't shed any light on the issue.



My code is below:



CustomWebApplicationFactory:



using Microsoft.AspNetCore.Authentication.AzureAD.UI;
using Microsoft.AspNetCore.Authentication.OpenIdConnect;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc.Testing;
using Microsoft.AspNetCore.TestHost;
using Microsoft.Extensions.DependencyInjection;

namespace WebPortal.Int.Tests

/// <summary>
/// Based on https://fullstackmark.com/post/20/painless-integration-testing-with-aspnet-core-web-api
/// </summary>
public class CustomWebApplicationFactory<TStartup> : WebApplicationFactory<Startup> where TStartup : class

public CustomWebApplicationFactory()

protected override void ConfigureWebHost(IWebHostBuilder builder)

builder
.ConfigureTestServices(
services =>

services.Configure(AzureADDefaults.OpenIdScheme, (System.Action<OpenIdConnectOptions>)(o =>

// CookieContainer doesn't allow cookies from other paths
o.CorrelationCookie.Path = "/";
o.NonceCookie.Path = "/";
));

)
.UseEnvironment("Production")
.UseStartup<Startup>();






AuthenticationTests:



using Microsoft.AspNetCore.Mvc.Testing;
using System;
using System.Net.Http;
using System.Threading.Tasks;
using Xunit;

namespace WebPortal.Int.Tests

public class AuthenticationTests : IClassFixture<CustomWebApplicationFactory<Startup>>

private HttpClient _httpClient get;

public AuthenticationTests(CustomWebApplicationFactory<Startup> fixture)

WebApplicationFactoryClientOptions webAppFactoryClientOptions = new WebApplicationFactoryClientOptions

// Disallow redirect so that we can check the following: Status code is redirect and redirect url is login url
// As per https://docs.microsoft.com/en-us/aspnet/core/test/integration-tests?view=aspnetcore-2.2#test-a-secure-endpoint
AllowAutoRedirect = false
;

_httpClient = fixture.CreateClient(webAppFactoryClientOptions);


[Theory]
[InlineData("/")]
[InlineData("/Index")]
[InlineData("/Error")]
public async Task Get_PagesNotRequiringAuthenticationWithoutAuthentication_ReturnsSuccessCode(string url)

// Act
HttpResponseMessage response = await _httpClient.GetAsync(url);

// Assert
try

response.EnsureSuccessStatusCode();

catch (HttpRequestException ex)

Console.WriteLine(ex.Message, ex.InnerException.Message);






Startup:



using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using WebPortal.Authentication;
using WebPortal.Common.ConfigurationOptions;
using WebPortal.DataAccess;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.AzureAD.UI;
using Microsoft.AspNetCore.Authentication.OpenIdConnect;
using Microsoft.AspNetCore.Http;

namespace WebPortal

public class Startup

public Startup(IConfiguration configuration)

Configuration = configuration;


public IConfiguration Configuration get;

// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)

services.Configure<CookiePolicyOptions>(options =>

// This lambda determines whether user consent for non-essential cookies is needed for a given request.
options.CheckConsentNeeded = context => false;
options.MinimumSameSitePolicy = SameSiteMode.None;
);

services.AddOptions<PowerBiSettings>()
.Bind(Configuration.GetSection("PowerBI"))
.ValidateDataAnnotations()
.Validate(o => o.AreSettingsValid());

services.AddOptions<AzureActiveDirectorySettings>()
.Bind(Configuration.GetSection("AzureAd"))
.ValidateDataAnnotations()
.Validate(o => o.AreSettingsValid());

services.AddAuthentication(AzureADDefaults.AuthenticationScheme)
.AddAzureAD(options => Configuration.Bind("AzureAd", options))
.AddCookie();

services.Configure<OpenIdConnectOptions>(AzureADDefaults.OpenIdScheme, options =>

options.Authority = options.Authority + "/v2.0/";
options.TokenValidationParameters.ValidateIssuer = false;
);

services.AddTransient<Authentication.IAuthenticationHandler, AuthenticationHandler>();
services.AddTransient<IReportRepository, ReportRepository>();

services.AddHttpContextAccessor();

services
.AddMvc()
.SetCompatibilityVersion(CompatibilityVersion.Version_2_2)
.AddRazorPagesOptions(options =>

options.Conventions.AuthorizePage("/Reports");
);


// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env)

var builder = new ConfigurationBuilder();

if (env.IsDevelopment())

app.UseDeveloperExceptionPage();

builder.AddUserSecrets<Startup>();

else

app.UseExceptionHandler("/Error");
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();


app.UseHttpsRedirection();
app.UseStaticFiles();

app.UseAuthentication();

app.UseMvc();





Error output:



[xUnit.net 00:00:00.00] xUnit.net VSTest Adapter v2.4.1 (64-bit .NET Core 4.6.27317.07)
[xUnit.net 00:00:01.30] Discovering: WebPortal.Int.Tests
[xUnit.net 00:00:01.40] Discovered: WebPortal.Int.Tests
[xUnit.net 00:00:01.41] Starting: WebPortal.Int.Tests
info: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[0]
User profile is available. Using 'C:UsersVssAdministratorAppDataLocalASP.NETDataProtection-Keys' as key repository and Windows DPAPI to encrypt keys at rest.
info: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[58]
Creating key dd820f09-8139-4d7d-954a-399923660f42 with creation date 2019-03-18 22:13:27Z, activation date 2019-03-18 22:13:27Z, and expiration date 2019-06-16 22:13:27Z.
info: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[39]
Writing data to file 'C:UsersVssAdministratorAppDataLocalASP.NETDataProtection-Keyskey-dd820f09-8139-4d7d-954a-399923660f42.xml'.
info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
Request starting HTTP/2.0 GET http://localhost/Index
warn: Microsoft.AspNetCore.HttpsPolicy.HttpsRedirectionMiddleware[3]
Failed to determine the https port for redirect.
fail: Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware[1]
An unhandled exception has occurred while executing the request.
System.ArgumentNullException: Value cannot be null.
Parameter name: uriString
at System.Uri..ctor(String uriString)
at Microsoft.AspNetCore.Authentication.AzureAD.UI.OpenIdConnectOptionsConfiguration.Configure(String name, OpenIdConnectOptions options)
at Microsoft.Extensions.Options.OptionsFactory`1.Create(String name)
at Microsoft.Extensions.Options.OptionsMonitor`1.<>c__DisplayClass10_0.<Get>b__0()
at System.Lazy`1.ViaFactory(LazyThreadSafetyMode mode)
at System.Lazy`1.ExecutionAndPublication(LazyHelper executionAndPublication, Boolean useDefaultConstructor)
at System.Lazy`1.CreateValue()
at Microsoft.Extensions.Options.OptionsCache`1.GetOrAdd(String name, Func`1 createOptions)
at Microsoft.Extensions.Options.OptionsMonitor`1.Get(String name)
at Microsoft.AspNetCore.Authentication.AuthenticationHandler`1.InitializeAsync(AuthenticationScheme scheme, HttpContext context)
at Microsoft.AspNetCore.Authentication.AuthenticationHandlerProvider.GetHandlerAsync(HttpContext context, String authenticationScheme)
at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context)
at Microsoft.AspNetCore.StaticFiles.StaticFileMiddleware.Invoke(HttpContext context)
at Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware.Invoke(HttpContext context)
fail: Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware[3]
An exception was thrown attempting to execute the error handler.
System.ArgumentNullException: Value cannot be null.
Parameter name: uriString
at System.Uri..ctor(String uriString)
at Microsoft.AspNetCore.Authentication.AzureAD.UI.OpenIdConnectOptionsConfiguration.Configure(String name, OpenIdConnectOptions options)
at Microsoft.Extensions.Options.OptionsFactory`1.Create(String name)
at Microsoft.Extensions.Options.OptionsMonitor`1.<>c__DisplayClass10_0.<Get>b__0()
at System.Lazy`1.ViaFactory(LazyThreadSafetyMode mode)
--- End of stack trace from previous location where exception was thrown ---
at System.Lazy`1.CreateValue()
at Microsoft.Extensions.Options.OptionsCache`1.GetOrAdd(String name, Func`1 createOptions)
at Microsoft.Extensions.Options.OptionsMonitor`1.Get(String name)
at Microsoft.AspNetCore.Authentication.AuthenticationHandler`1.InitializeAsync(AuthenticationScheme scheme, HttpContext context)
at Microsoft.AspNetCore.Authentication.AuthenticationHandlerProvider.GetHandlerAsync(HttpContext context, String authenticationScheme)
at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context)
at Microsoft.AspNetCore.StaticFiles.StaticFileMiddleware.Invoke(HttpContext context)
at Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware.Invoke(HttpContext context)
info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
Request finished in 449.9633ms 500
info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
Request starting HTTP/2.0 GET http://localhost/Error
fail: Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware[1]
An unhandled exception has occurred while executing the request.
System.ArgumentNullException: Value cannot be null.
Parameter name: uriString
at System.Uri..ctor(String uriString)
at Microsoft.AspNetCore.Authentication.AzureAD.UI.OpenIdConnectOptionsConfiguration.Configure(String name, OpenIdConnectOptions options)
at Microsoft.Extensions.Options.OptionsFactory`1.Create(String name)
at Microsoft.Extensions.Options.OptionsMonitor`1.<>c__DisplayClass10_0.<Get>b__0()
at System.Lazy`1.ViaFactory(LazyThreadSafetyMode mode)
--- End of stack trace from previous location where exception was thrown ---
at System.Lazy`1.CreateValue()
at Microsoft.Extensions.Options.OptionsCache`1.GetOrAdd(String name, Func`1 createOptions)
at Microsoft.Extensions.Options.OptionsMonitor`1.Get(String name)
at Microsoft.AspNetCore.Authentication.AuthenticationHandler`1.InitializeAsync(AuthenticationScheme scheme, HttpContext context)
at Microsoft.AspNetCore.Authentication.AuthenticationHandlerProvider.GetHandlerAsync(HttpContext context, String authenticationScheme)
at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context)
at Microsoft.AspNetCore.StaticFiles.StaticFileMiddleware.Invoke(HttpContext context)
at Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware.Invoke(HttpContext context)
[xUnit.net 00:00:02.61] WebPortal.Int.Tests.AuthenticationTests.Get_PagesNotRequiringAuthenticationWithoutAuthentication_ReturnsSuccessCode(url: "/Index") [FAIL]
[xUnit.net 00:00:02.61] System.ArgumentNullException : Value cannot be null.
[xUnit.net 00:00:02.61] Parameter name: uriString
[xUnit.net 00:00:02.61] Stack Trace:
[xUnit.net 00:00:02.61] at System.Uri..ctor(String uriString)
[xUnit.net 00:00:02.61] at Microsoft.AspNetCore.Authentication.AzureAD.UI.OpenIdConnectOptionsConfiguration.Configure(String name, OpenIdConnectOptions options)
[xUnit.net 00:00:02.61] at Microsoft.Extensions.Options.OptionsFactory`1.Create(String name)
[xUnit.net 00:00:02.61] at Microsoft.Extensions.Options.OptionsMonitor`1.<>c__DisplayClass10_0.<Get>b__0()
[xUnit.net 00:00:02.61] at System.Lazy`1.ViaFactory(LazyThreadSafetyMode mode)
[xUnit.net 00:00:02.61] --- End of stack trace from previous location where exception was thrown ---
[xUnit.net 00:00:02.61] at System.Lazy`1.CreateValue()
[xUnit.net 00:00:02.61] at Microsoft.Extensions.Options.OptionsCache`1.GetOrAdd(String name, Func`1 createOptions)
[xUnit.net 00:00:02.61] at Microsoft.Extensions.Options.OptionsMonitor`1.Get(String name)
[xUnit.net 00:00:02.61] at Microsoft.AspNetCore.Authentication.AuthenticationHandler`1.InitializeAsync(AuthenticationScheme scheme, HttpContext context)
[xUnit.net 00:00:02.61] at Microsoft.AspNetCore.Authentication.AuthenticationHandlerProvider.GetHandlerAsync(HttpContext context, String authenticationScheme)
[xUnit.net 00:00:02.61] at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context)
[xUnit.net 00:00:02.61] at Microsoft.AspNetCore.StaticFiles.StaticFileMiddleware.Invoke(HttpContext context)
[xUnit.net 00:00:02.61] at Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware.Invoke(HttpContext context)
[xUnit.net 00:00:02.61] at Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware.Invoke(HttpContext context)
[xUnit.net 00:00:02.61] at Microsoft.AspNetCore.TestHost.HttpContextBuilder.<>c__DisplayClass10_0.<<SendAsync>b__0>d.MoveNext()
[xUnit.net 00:00:02.61] --- End of stack trace from previous location where exception was thrown ---
[xUnit.net 00:00:02.61] at Microsoft.AspNetCore.TestHost.ClientHandler.SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
[xUnit.net 00:00:02.61] at Microsoft.AspNetCore.Mvc.Testing.Handlers.CookieContainerHandler.SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
[xUnit.net 00:00:02.61] at Microsoft.AspNetCore.Mvc.Testing.Handlers.RedirectHandler.SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)[xUnit.net 00:00:02.63] WebPortal.Int.Tests.AuthenticationTests.Get_PagesNotRequiringAuthenticationWithoutAuthentication_ReturnsSuccessCode(url: "/Error") [FAIL]
[xUnit.net 00:00:02.64] WebPortal.Int.Tests.AuthenticationTests.Get_PagesNotRequiringAuthenticationWithoutAuthentication_ReturnsSuccessCode(url: "") [FAIL]

[xUnit.net 00:00:02.61] at System.Net.Http.HttpClient.FinishSendAsyncBuffered(Task`1 sendTask, HttpRequestMessage request, CancellationTokenSource cts, Boolean disposeCts)
[xUnit.net 00:00:02.61] D:a1sWebPortal.Int.TestsAuthenticationTests.cs(24,0): at WebPortal.Int.Tests.AuthenticationTests.Get_PagesNotRequiringAuthenticationWithoutAuthentication_ReturnsSuccessCode(String url)
[xUnit.net 00:00:02.61] --- End of stack trace from previous location where exception was thrown ---


edit



It isn't very clear to me where/why I am getting a null reference because as far as I can tell my OpenIdConnectOptions configuration is correct (and it works with AAD SSO).










share|improve this question



















  • 2





    Hi, may be stupid question and you have already checked it. But have you tried to move: "builder.AddUserSecrets<Startup>();" outside of env.IsDevelopment() ?

    – Nikolay
    Mar 20 at 8:20







  • 1





    Seeing your stracktrace, I'm pretty sure your question is answered here

    – Jesse de Wit
    Mar 20 at 18:20












  • @Nikolay yes I have tried this thank you.

    – Matt Stannett
    Mar 20 at 20:28











  • @JessedeWit that suggestion didn't fix it my issue but it did put me onto the fact that my AzureAd configuration wasn't being loaded properly during the tests. Hardcoding the values in worked then I realised that I hadn't called .Build() on my ConfigurationBuilder and assigned the value to the Configuration object. This also meant that I moved the code to include the secrets into the Startup constructor.

    – Matt Stannett
    Mar 20 at 20:30

















4















I have an ASP.NET Core 2.2 Razor Pages Web App that I have written some integration tests for following the official guide.



I can get the tests to run locally using dotnet test or the test runners built into Visual Studio. However, on the build server (Azure DevOps Hosted 2017 agent) the tests will return a 500 error. I thought it might be related to user secrets as stated on Scott Hanselman's guide but I am still getting the same error, even after implementing some of his suggested fixes (I don't believe I need all of them) :



  • Added builder.AddUserSecrets<Startup>(); to Startup.

  • Implemented a CustomWebApplicationFactory to set the environment to "Development" - code below has this as "Production" to reproduce the failure.

I also sanity checked against this guide which is more controller focused but since I only care about the response codes at this stage it serves my purpose. I have downloaded the verbose logs and they don't shed any light on the issue.



My code is below:



CustomWebApplicationFactory:



using Microsoft.AspNetCore.Authentication.AzureAD.UI;
using Microsoft.AspNetCore.Authentication.OpenIdConnect;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc.Testing;
using Microsoft.AspNetCore.TestHost;
using Microsoft.Extensions.DependencyInjection;

namespace WebPortal.Int.Tests

/// <summary>
/// Based on https://fullstackmark.com/post/20/painless-integration-testing-with-aspnet-core-web-api
/// </summary>
public class CustomWebApplicationFactory<TStartup> : WebApplicationFactory<Startup> where TStartup : class

public CustomWebApplicationFactory()

protected override void ConfigureWebHost(IWebHostBuilder builder)

builder
.ConfigureTestServices(
services =>

services.Configure(AzureADDefaults.OpenIdScheme, (System.Action<OpenIdConnectOptions>)(o =>

// CookieContainer doesn't allow cookies from other paths
o.CorrelationCookie.Path = "/";
o.NonceCookie.Path = "/";
));

)
.UseEnvironment("Production")
.UseStartup<Startup>();






AuthenticationTests:



using Microsoft.AspNetCore.Mvc.Testing;
using System;
using System.Net.Http;
using System.Threading.Tasks;
using Xunit;

namespace WebPortal.Int.Tests

public class AuthenticationTests : IClassFixture<CustomWebApplicationFactory<Startup>>

private HttpClient _httpClient get;

public AuthenticationTests(CustomWebApplicationFactory<Startup> fixture)

WebApplicationFactoryClientOptions webAppFactoryClientOptions = new WebApplicationFactoryClientOptions

// Disallow redirect so that we can check the following: Status code is redirect and redirect url is login url
// As per https://docs.microsoft.com/en-us/aspnet/core/test/integration-tests?view=aspnetcore-2.2#test-a-secure-endpoint
AllowAutoRedirect = false
;

_httpClient = fixture.CreateClient(webAppFactoryClientOptions);


[Theory]
[InlineData("/")]
[InlineData("/Index")]
[InlineData("/Error")]
public async Task Get_PagesNotRequiringAuthenticationWithoutAuthentication_ReturnsSuccessCode(string url)

// Act
HttpResponseMessage response = await _httpClient.GetAsync(url);

// Assert
try

response.EnsureSuccessStatusCode();

catch (HttpRequestException ex)

Console.WriteLine(ex.Message, ex.InnerException.Message);






Startup:



using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using WebPortal.Authentication;
using WebPortal.Common.ConfigurationOptions;
using WebPortal.DataAccess;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.AzureAD.UI;
using Microsoft.AspNetCore.Authentication.OpenIdConnect;
using Microsoft.AspNetCore.Http;

namespace WebPortal

public class Startup

public Startup(IConfiguration configuration)

Configuration = configuration;


public IConfiguration Configuration get;

// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)

services.Configure<CookiePolicyOptions>(options =>

// This lambda determines whether user consent for non-essential cookies is needed for a given request.
options.CheckConsentNeeded = context => false;
options.MinimumSameSitePolicy = SameSiteMode.None;
);

services.AddOptions<PowerBiSettings>()
.Bind(Configuration.GetSection("PowerBI"))
.ValidateDataAnnotations()
.Validate(o => o.AreSettingsValid());

services.AddOptions<AzureActiveDirectorySettings>()
.Bind(Configuration.GetSection("AzureAd"))
.ValidateDataAnnotations()
.Validate(o => o.AreSettingsValid());

services.AddAuthentication(AzureADDefaults.AuthenticationScheme)
.AddAzureAD(options => Configuration.Bind("AzureAd", options))
.AddCookie();

services.Configure<OpenIdConnectOptions>(AzureADDefaults.OpenIdScheme, options =>

options.Authority = options.Authority + "/v2.0/";
options.TokenValidationParameters.ValidateIssuer = false;
);

services.AddTransient<Authentication.IAuthenticationHandler, AuthenticationHandler>();
services.AddTransient<IReportRepository, ReportRepository>();

services.AddHttpContextAccessor();

services
.AddMvc()
.SetCompatibilityVersion(CompatibilityVersion.Version_2_2)
.AddRazorPagesOptions(options =>

options.Conventions.AuthorizePage("/Reports");
);


// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env)

var builder = new ConfigurationBuilder();

if (env.IsDevelopment())

app.UseDeveloperExceptionPage();

builder.AddUserSecrets<Startup>();

else

app.UseExceptionHandler("/Error");
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();


app.UseHttpsRedirection();
app.UseStaticFiles();

app.UseAuthentication();

app.UseMvc();





Error output:



[xUnit.net 00:00:00.00] xUnit.net VSTest Adapter v2.4.1 (64-bit .NET Core 4.6.27317.07)
[xUnit.net 00:00:01.30] Discovering: WebPortal.Int.Tests
[xUnit.net 00:00:01.40] Discovered: WebPortal.Int.Tests
[xUnit.net 00:00:01.41] Starting: WebPortal.Int.Tests
info: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[0]
User profile is available. Using 'C:UsersVssAdministratorAppDataLocalASP.NETDataProtection-Keys' as key repository and Windows DPAPI to encrypt keys at rest.
info: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[58]
Creating key dd820f09-8139-4d7d-954a-399923660f42 with creation date 2019-03-18 22:13:27Z, activation date 2019-03-18 22:13:27Z, and expiration date 2019-06-16 22:13:27Z.
info: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[39]
Writing data to file 'C:UsersVssAdministratorAppDataLocalASP.NETDataProtection-Keyskey-dd820f09-8139-4d7d-954a-399923660f42.xml'.
info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
Request starting HTTP/2.0 GET http://localhost/Index
warn: Microsoft.AspNetCore.HttpsPolicy.HttpsRedirectionMiddleware[3]
Failed to determine the https port for redirect.
fail: Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware[1]
An unhandled exception has occurred while executing the request.
System.ArgumentNullException: Value cannot be null.
Parameter name: uriString
at System.Uri..ctor(String uriString)
at Microsoft.AspNetCore.Authentication.AzureAD.UI.OpenIdConnectOptionsConfiguration.Configure(String name, OpenIdConnectOptions options)
at Microsoft.Extensions.Options.OptionsFactory`1.Create(String name)
at Microsoft.Extensions.Options.OptionsMonitor`1.<>c__DisplayClass10_0.<Get>b__0()
at System.Lazy`1.ViaFactory(LazyThreadSafetyMode mode)
at System.Lazy`1.ExecutionAndPublication(LazyHelper executionAndPublication, Boolean useDefaultConstructor)
at System.Lazy`1.CreateValue()
at Microsoft.Extensions.Options.OptionsCache`1.GetOrAdd(String name, Func`1 createOptions)
at Microsoft.Extensions.Options.OptionsMonitor`1.Get(String name)
at Microsoft.AspNetCore.Authentication.AuthenticationHandler`1.InitializeAsync(AuthenticationScheme scheme, HttpContext context)
at Microsoft.AspNetCore.Authentication.AuthenticationHandlerProvider.GetHandlerAsync(HttpContext context, String authenticationScheme)
at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context)
at Microsoft.AspNetCore.StaticFiles.StaticFileMiddleware.Invoke(HttpContext context)
at Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware.Invoke(HttpContext context)
fail: Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware[3]
An exception was thrown attempting to execute the error handler.
System.ArgumentNullException: Value cannot be null.
Parameter name: uriString
at System.Uri..ctor(String uriString)
at Microsoft.AspNetCore.Authentication.AzureAD.UI.OpenIdConnectOptionsConfiguration.Configure(String name, OpenIdConnectOptions options)
at Microsoft.Extensions.Options.OptionsFactory`1.Create(String name)
at Microsoft.Extensions.Options.OptionsMonitor`1.<>c__DisplayClass10_0.<Get>b__0()
at System.Lazy`1.ViaFactory(LazyThreadSafetyMode mode)
--- End of stack trace from previous location where exception was thrown ---
at System.Lazy`1.CreateValue()
at Microsoft.Extensions.Options.OptionsCache`1.GetOrAdd(String name, Func`1 createOptions)
at Microsoft.Extensions.Options.OptionsMonitor`1.Get(String name)
at Microsoft.AspNetCore.Authentication.AuthenticationHandler`1.InitializeAsync(AuthenticationScheme scheme, HttpContext context)
at Microsoft.AspNetCore.Authentication.AuthenticationHandlerProvider.GetHandlerAsync(HttpContext context, String authenticationScheme)
at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context)
at Microsoft.AspNetCore.StaticFiles.StaticFileMiddleware.Invoke(HttpContext context)
at Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware.Invoke(HttpContext context)
info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
Request finished in 449.9633ms 500
info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
Request starting HTTP/2.0 GET http://localhost/Error
fail: Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware[1]
An unhandled exception has occurred while executing the request.
System.ArgumentNullException: Value cannot be null.
Parameter name: uriString
at System.Uri..ctor(String uriString)
at Microsoft.AspNetCore.Authentication.AzureAD.UI.OpenIdConnectOptionsConfiguration.Configure(String name, OpenIdConnectOptions options)
at Microsoft.Extensions.Options.OptionsFactory`1.Create(String name)
at Microsoft.Extensions.Options.OptionsMonitor`1.<>c__DisplayClass10_0.<Get>b__0()
at System.Lazy`1.ViaFactory(LazyThreadSafetyMode mode)
--- End of stack trace from previous location where exception was thrown ---
at System.Lazy`1.CreateValue()
at Microsoft.Extensions.Options.OptionsCache`1.GetOrAdd(String name, Func`1 createOptions)
at Microsoft.Extensions.Options.OptionsMonitor`1.Get(String name)
at Microsoft.AspNetCore.Authentication.AuthenticationHandler`1.InitializeAsync(AuthenticationScheme scheme, HttpContext context)
at Microsoft.AspNetCore.Authentication.AuthenticationHandlerProvider.GetHandlerAsync(HttpContext context, String authenticationScheme)
at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context)
at Microsoft.AspNetCore.StaticFiles.StaticFileMiddleware.Invoke(HttpContext context)
at Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware.Invoke(HttpContext context)
[xUnit.net 00:00:02.61] WebPortal.Int.Tests.AuthenticationTests.Get_PagesNotRequiringAuthenticationWithoutAuthentication_ReturnsSuccessCode(url: "/Index") [FAIL]
[xUnit.net 00:00:02.61] System.ArgumentNullException : Value cannot be null.
[xUnit.net 00:00:02.61] Parameter name: uriString
[xUnit.net 00:00:02.61] Stack Trace:
[xUnit.net 00:00:02.61] at System.Uri..ctor(String uriString)
[xUnit.net 00:00:02.61] at Microsoft.AspNetCore.Authentication.AzureAD.UI.OpenIdConnectOptionsConfiguration.Configure(String name, OpenIdConnectOptions options)
[xUnit.net 00:00:02.61] at Microsoft.Extensions.Options.OptionsFactory`1.Create(String name)
[xUnit.net 00:00:02.61] at Microsoft.Extensions.Options.OptionsMonitor`1.<>c__DisplayClass10_0.<Get>b__0()
[xUnit.net 00:00:02.61] at System.Lazy`1.ViaFactory(LazyThreadSafetyMode mode)
[xUnit.net 00:00:02.61] --- End of stack trace from previous location where exception was thrown ---
[xUnit.net 00:00:02.61] at System.Lazy`1.CreateValue()
[xUnit.net 00:00:02.61] at Microsoft.Extensions.Options.OptionsCache`1.GetOrAdd(String name, Func`1 createOptions)
[xUnit.net 00:00:02.61] at Microsoft.Extensions.Options.OptionsMonitor`1.Get(String name)
[xUnit.net 00:00:02.61] at Microsoft.AspNetCore.Authentication.AuthenticationHandler`1.InitializeAsync(AuthenticationScheme scheme, HttpContext context)
[xUnit.net 00:00:02.61] at Microsoft.AspNetCore.Authentication.AuthenticationHandlerProvider.GetHandlerAsync(HttpContext context, String authenticationScheme)
[xUnit.net 00:00:02.61] at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context)
[xUnit.net 00:00:02.61] at Microsoft.AspNetCore.StaticFiles.StaticFileMiddleware.Invoke(HttpContext context)
[xUnit.net 00:00:02.61] at Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware.Invoke(HttpContext context)
[xUnit.net 00:00:02.61] at Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware.Invoke(HttpContext context)
[xUnit.net 00:00:02.61] at Microsoft.AspNetCore.TestHost.HttpContextBuilder.<>c__DisplayClass10_0.<<SendAsync>b__0>d.MoveNext()
[xUnit.net 00:00:02.61] --- End of stack trace from previous location where exception was thrown ---
[xUnit.net 00:00:02.61] at Microsoft.AspNetCore.TestHost.ClientHandler.SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
[xUnit.net 00:00:02.61] at Microsoft.AspNetCore.Mvc.Testing.Handlers.CookieContainerHandler.SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
[xUnit.net 00:00:02.61] at Microsoft.AspNetCore.Mvc.Testing.Handlers.RedirectHandler.SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)[xUnit.net 00:00:02.63] WebPortal.Int.Tests.AuthenticationTests.Get_PagesNotRequiringAuthenticationWithoutAuthentication_ReturnsSuccessCode(url: "/Error") [FAIL]
[xUnit.net 00:00:02.64] WebPortal.Int.Tests.AuthenticationTests.Get_PagesNotRequiringAuthenticationWithoutAuthentication_ReturnsSuccessCode(url: "") [FAIL]

[xUnit.net 00:00:02.61] at System.Net.Http.HttpClient.FinishSendAsyncBuffered(Task`1 sendTask, HttpRequestMessage request, CancellationTokenSource cts, Boolean disposeCts)
[xUnit.net 00:00:02.61] D:a1sWebPortal.Int.TestsAuthenticationTests.cs(24,0): at WebPortal.Int.Tests.AuthenticationTests.Get_PagesNotRequiringAuthenticationWithoutAuthentication_ReturnsSuccessCode(String url)
[xUnit.net 00:00:02.61] --- End of stack trace from previous location where exception was thrown ---


edit



It isn't very clear to me where/why I am getting a null reference because as far as I can tell my OpenIdConnectOptions configuration is correct (and it works with AAD SSO).










share|improve this question



















  • 2





    Hi, may be stupid question and you have already checked it. But have you tried to move: "builder.AddUserSecrets<Startup>();" outside of env.IsDevelopment() ?

    – Nikolay
    Mar 20 at 8:20







  • 1





    Seeing your stracktrace, I'm pretty sure your question is answered here

    – Jesse de Wit
    Mar 20 at 18:20












  • @Nikolay yes I have tried this thank you.

    – Matt Stannett
    Mar 20 at 20:28











  • @JessedeWit that suggestion didn't fix it my issue but it did put me onto the fact that my AzureAd configuration wasn't being loaded properly during the tests. Hardcoding the values in worked then I realised that I hadn't called .Build() on my ConfigurationBuilder and assigned the value to the Configuration object. This also meant that I moved the code to include the secrets into the Startup constructor.

    – Matt Stannett
    Mar 20 at 20:30













4












4








4


1






I have an ASP.NET Core 2.2 Razor Pages Web App that I have written some integration tests for following the official guide.



I can get the tests to run locally using dotnet test or the test runners built into Visual Studio. However, on the build server (Azure DevOps Hosted 2017 agent) the tests will return a 500 error. I thought it might be related to user secrets as stated on Scott Hanselman's guide but I am still getting the same error, even after implementing some of his suggested fixes (I don't believe I need all of them) :



  • Added builder.AddUserSecrets<Startup>(); to Startup.

  • Implemented a CustomWebApplicationFactory to set the environment to "Development" - code below has this as "Production" to reproduce the failure.

I also sanity checked against this guide which is more controller focused but since I only care about the response codes at this stage it serves my purpose. I have downloaded the verbose logs and they don't shed any light on the issue.



My code is below:



CustomWebApplicationFactory:



using Microsoft.AspNetCore.Authentication.AzureAD.UI;
using Microsoft.AspNetCore.Authentication.OpenIdConnect;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc.Testing;
using Microsoft.AspNetCore.TestHost;
using Microsoft.Extensions.DependencyInjection;

namespace WebPortal.Int.Tests

/// <summary>
/// Based on https://fullstackmark.com/post/20/painless-integration-testing-with-aspnet-core-web-api
/// </summary>
public class CustomWebApplicationFactory<TStartup> : WebApplicationFactory<Startup> where TStartup : class

public CustomWebApplicationFactory()

protected override void ConfigureWebHost(IWebHostBuilder builder)

builder
.ConfigureTestServices(
services =>

services.Configure(AzureADDefaults.OpenIdScheme, (System.Action<OpenIdConnectOptions>)(o =>

// CookieContainer doesn't allow cookies from other paths
o.CorrelationCookie.Path = "/";
o.NonceCookie.Path = "/";
));

)
.UseEnvironment("Production")
.UseStartup<Startup>();






AuthenticationTests:



using Microsoft.AspNetCore.Mvc.Testing;
using System;
using System.Net.Http;
using System.Threading.Tasks;
using Xunit;

namespace WebPortal.Int.Tests

public class AuthenticationTests : IClassFixture<CustomWebApplicationFactory<Startup>>

private HttpClient _httpClient get;

public AuthenticationTests(CustomWebApplicationFactory<Startup> fixture)

WebApplicationFactoryClientOptions webAppFactoryClientOptions = new WebApplicationFactoryClientOptions

// Disallow redirect so that we can check the following: Status code is redirect and redirect url is login url
// As per https://docs.microsoft.com/en-us/aspnet/core/test/integration-tests?view=aspnetcore-2.2#test-a-secure-endpoint
AllowAutoRedirect = false
;

_httpClient = fixture.CreateClient(webAppFactoryClientOptions);


[Theory]
[InlineData("/")]
[InlineData("/Index")]
[InlineData("/Error")]
public async Task Get_PagesNotRequiringAuthenticationWithoutAuthentication_ReturnsSuccessCode(string url)

// Act
HttpResponseMessage response = await _httpClient.GetAsync(url);

// Assert
try

response.EnsureSuccessStatusCode();

catch (HttpRequestException ex)

Console.WriteLine(ex.Message, ex.InnerException.Message);






Startup:



using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using WebPortal.Authentication;
using WebPortal.Common.ConfigurationOptions;
using WebPortal.DataAccess;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.AzureAD.UI;
using Microsoft.AspNetCore.Authentication.OpenIdConnect;
using Microsoft.AspNetCore.Http;

namespace WebPortal

public class Startup

public Startup(IConfiguration configuration)

Configuration = configuration;


public IConfiguration Configuration get;

// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)

services.Configure<CookiePolicyOptions>(options =>

// This lambda determines whether user consent for non-essential cookies is needed for a given request.
options.CheckConsentNeeded = context => false;
options.MinimumSameSitePolicy = SameSiteMode.None;
);

services.AddOptions<PowerBiSettings>()
.Bind(Configuration.GetSection("PowerBI"))
.ValidateDataAnnotations()
.Validate(o => o.AreSettingsValid());

services.AddOptions<AzureActiveDirectorySettings>()
.Bind(Configuration.GetSection("AzureAd"))
.ValidateDataAnnotations()
.Validate(o => o.AreSettingsValid());

services.AddAuthentication(AzureADDefaults.AuthenticationScheme)
.AddAzureAD(options => Configuration.Bind("AzureAd", options))
.AddCookie();

services.Configure<OpenIdConnectOptions>(AzureADDefaults.OpenIdScheme, options =>

options.Authority = options.Authority + "/v2.0/";
options.TokenValidationParameters.ValidateIssuer = false;
);

services.AddTransient<Authentication.IAuthenticationHandler, AuthenticationHandler>();
services.AddTransient<IReportRepository, ReportRepository>();

services.AddHttpContextAccessor();

services
.AddMvc()
.SetCompatibilityVersion(CompatibilityVersion.Version_2_2)
.AddRazorPagesOptions(options =>

options.Conventions.AuthorizePage("/Reports");
);


// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env)

var builder = new ConfigurationBuilder();

if (env.IsDevelopment())

app.UseDeveloperExceptionPage();

builder.AddUserSecrets<Startup>();

else

app.UseExceptionHandler("/Error");
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();


app.UseHttpsRedirection();
app.UseStaticFiles();

app.UseAuthentication();

app.UseMvc();





Error output:



[xUnit.net 00:00:00.00] xUnit.net VSTest Adapter v2.4.1 (64-bit .NET Core 4.6.27317.07)
[xUnit.net 00:00:01.30] Discovering: WebPortal.Int.Tests
[xUnit.net 00:00:01.40] Discovered: WebPortal.Int.Tests
[xUnit.net 00:00:01.41] Starting: WebPortal.Int.Tests
info: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[0]
User profile is available. Using 'C:UsersVssAdministratorAppDataLocalASP.NETDataProtection-Keys' as key repository and Windows DPAPI to encrypt keys at rest.
info: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[58]
Creating key dd820f09-8139-4d7d-954a-399923660f42 with creation date 2019-03-18 22:13:27Z, activation date 2019-03-18 22:13:27Z, and expiration date 2019-06-16 22:13:27Z.
info: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[39]
Writing data to file 'C:UsersVssAdministratorAppDataLocalASP.NETDataProtection-Keyskey-dd820f09-8139-4d7d-954a-399923660f42.xml'.
info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
Request starting HTTP/2.0 GET http://localhost/Index
warn: Microsoft.AspNetCore.HttpsPolicy.HttpsRedirectionMiddleware[3]
Failed to determine the https port for redirect.
fail: Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware[1]
An unhandled exception has occurred while executing the request.
System.ArgumentNullException: Value cannot be null.
Parameter name: uriString
at System.Uri..ctor(String uriString)
at Microsoft.AspNetCore.Authentication.AzureAD.UI.OpenIdConnectOptionsConfiguration.Configure(String name, OpenIdConnectOptions options)
at Microsoft.Extensions.Options.OptionsFactory`1.Create(String name)
at Microsoft.Extensions.Options.OptionsMonitor`1.<>c__DisplayClass10_0.<Get>b__0()
at System.Lazy`1.ViaFactory(LazyThreadSafetyMode mode)
at System.Lazy`1.ExecutionAndPublication(LazyHelper executionAndPublication, Boolean useDefaultConstructor)
at System.Lazy`1.CreateValue()
at Microsoft.Extensions.Options.OptionsCache`1.GetOrAdd(String name, Func`1 createOptions)
at Microsoft.Extensions.Options.OptionsMonitor`1.Get(String name)
at Microsoft.AspNetCore.Authentication.AuthenticationHandler`1.InitializeAsync(AuthenticationScheme scheme, HttpContext context)
at Microsoft.AspNetCore.Authentication.AuthenticationHandlerProvider.GetHandlerAsync(HttpContext context, String authenticationScheme)
at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context)
at Microsoft.AspNetCore.StaticFiles.StaticFileMiddleware.Invoke(HttpContext context)
at Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware.Invoke(HttpContext context)
fail: Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware[3]
An exception was thrown attempting to execute the error handler.
System.ArgumentNullException: Value cannot be null.
Parameter name: uriString
at System.Uri..ctor(String uriString)
at Microsoft.AspNetCore.Authentication.AzureAD.UI.OpenIdConnectOptionsConfiguration.Configure(String name, OpenIdConnectOptions options)
at Microsoft.Extensions.Options.OptionsFactory`1.Create(String name)
at Microsoft.Extensions.Options.OptionsMonitor`1.<>c__DisplayClass10_0.<Get>b__0()
at System.Lazy`1.ViaFactory(LazyThreadSafetyMode mode)
--- End of stack trace from previous location where exception was thrown ---
at System.Lazy`1.CreateValue()
at Microsoft.Extensions.Options.OptionsCache`1.GetOrAdd(String name, Func`1 createOptions)
at Microsoft.Extensions.Options.OptionsMonitor`1.Get(String name)
at Microsoft.AspNetCore.Authentication.AuthenticationHandler`1.InitializeAsync(AuthenticationScheme scheme, HttpContext context)
at Microsoft.AspNetCore.Authentication.AuthenticationHandlerProvider.GetHandlerAsync(HttpContext context, String authenticationScheme)
at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context)
at Microsoft.AspNetCore.StaticFiles.StaticFileMiddleware.Invoke(HttpContext context)
at Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware.Invoke(HttpContext context)
info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
Request finished in 449.9633ms 500
info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
Request starting HTTP/2.0 GET http://localhost/Error
fail: Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware[1]
An unhandled exception has occurred while executing the request.
System.ArgumentNullException: Value cannot be null.
Parameter name: uriString
at System.Uri..ctor(String uriString)
at Microsoft.AspNetCore.Authentication.AzureAD.UI.OpenIdConnectOptionsConfiguration.Configure(String name, OpenIdConnectOptions options)
at Microsoft.Extensions.Options.OptionsFactory`1.Create(String name)
at Microsoft.Extensions.Options.OptionsMonitor`1.<>c__DisplayClass10_0.<Get>b__0()
at System.Lazy`1.ViaFactory(LazyThreadSafetyMode mode)
--- End of stack trace from previous location where exception was thrown ---
at System.Lazy`1.CreateValue()
at Microsoft.Extensions.Options.OptionsCache`1.GetOrAdd(String name, Func`1 createOptions)
at Microsoft.Extensions.Options.OptionsMonitor`1.Get(String name)
at Microsoft.AspNetCore.Authentication.AuthenticationHandler`1.InitializeAsync(AuthenticationScheme scheme, HttpContext context)
at Microsoft.AspNetCore.Authentication.AuthenticationHandlerProvider.GetHandlerAsync(HttpContext context, String authenticationScheme)
at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context)
at Microsoft.AspNetCore.StaticFiles.StaticFileMiddleware.Invoke(HttpContext context)
at Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware.Invoke(HttpContext context)
[xUnit.net 00:00:02.61] WebPortal.Int.Tests.AuthenticationTests.Get_PagesNotRequiringAuthenticationWithoutAuthentication_ReturnsSuccessCode(url: "/Index") [FAIL]
[xUnit.net 00:00:02.61] System.ArgumentNullException : Value cannot be null.
[xUnit.net 00:00:02.61] Parameter name: uriString
[xUnit.net 00:00:02.61] Stack Trace:
[xUnit.net 00:00:02.61] at System.Uri..ctor(String uriString)
[xUnit.net 00:00:02.61] at Microsoft.AspNetCore.Authentication.AzureAD.UI.OpenIdConnectOptionsConfiguration.Configure(String name, OpenIdConnectOptions options)
[xUnit.net 00:00:02.61] at Microsoft.Extensions.Options.OptionsFactory`1.Create(String name)
[xUnit.net 00:00:02.61] at Microsoft.Extensions.Options.OptionsMonitor`1.<>c__DisplayClass10_0.<Get>b__0()
[xUnit.net 00:00:02.61] at System.Lazy`1.ViaFactory(LazyThreadSafetyMode mode)
[xUnit.net 00:00:02.61] --- End of stack trace from previous location where exception was thrown ---
[xUnit.net 00:00:02.61] at System.Lazy`1.CreateValue()
[xUnit.net 00:00:02.61] at Microsoft.Extensions.Options.OptionsCache`1.GetOrAdd(String name, Func`1 createOptions)
[xUnit.net 00:00:02.61] at Microsoft.Extensions.Options.OptionsMonitor`1.Get(String name)
[xUnit.net 00:00:02.61] at Microsoft.AspNetCore.Authentication.AuthenticationHandler`1.InitializeAsync(AuthenticationScheme scheme, HttpContext context)
[xUnit.net 00:00:02.61] at Microsoft.AspNetCore.Authentication.AuthenticationHandlerProvider.GetHandlerAsync(HttpContext context, String authenticationScheme)
[xUnit.net 00:00:02.61] at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context)
[xUnit.net 00:00:02.61] at Microsoft.AspNetCore.StaticFiles.StaticFileMiddleware.Invoke(HttpContext context)
[xUnit.net 00:00:02.61] at Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware.Invoke(HttpContext context)
[xUnit.net 00:00:02.61] at Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware.Invoke(HttpContext context)
[xUnit.net 00:00:02.61] at Microsoft.AspNetCore.TestHost.HttpContextBuilder.<>c__DisplayClass10_0.<<SendAsync>b__0>d.MoveNext()
[xUnit.net 00:00:02.61] --- End of stack trace from previous location where exception was thrown ---
[xUnit.net 00:00:02.61] at Microsoft.AspNetCore.TestHost.ClientHandler.SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
[xUnit.net 00:00:02.61] at Microsoft.AspNetCore.Mvc.Testing.Handlers.CookieContainerHandler.SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
[xUnit.net 00:00:02.61] at Microsoft.AspNetCore.Mvc.Testing.Handlers.RedirectHandler.SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)[xUnit.net 00:00:02.63] WebPortal.Int.Tests.AuthenticationTests.Get_PagesNotRequiringAuthenticationWithoutAuthentication_ReturnsSuccessCode(url: "/Error") [FAIL]
[xUnit.net 00:00:02.64] WebPortal.Int.Tests.AuthenticationTests.Get_PagesNotRequiringAuthenticationWithoutAuthentication_ReturnsSuccessCode(url: "") [FAIL]

[xUnit.net 00:00:02.61] at System.Net.Http.HttpClient.FinishSendAsyncBuffered(Task`1 sendTask, HttpRequestMessage request, CancellationTokenSource cts, Boolean disposeCts)
[xUnit.net 00:00:02.61] D:a1sWebPortal.Int.TestsAuthenticationTests.cs(24,0): at WebPortal.Int.Tests.AuthenticationTests.Get_PagesNotRequiringAuthenticationWithoutAuthentication_ReturnsSuccessCode(String url)
[xUnit.net 00:00:02.61] --- End of stack trace from previous location where exception was thrown ---


edit



It isn't very clear to me where/why I am getting a null reference because as far as I can tell my OpenIdConnectOptions configuration is correct (and it works with AAD SSO).










share|improve this question
















I have an ASP.NET Core 2.2 Razor Pages Web App that I have written some integration tests for following the official guide.



I can get the tests to run locally using dotnet test or the test runners built into Visual Studio. However, on the build server (Azure DevOps Hosted 2017 agent) the tests will return a 500 error. I thought it might be related to user secrets as stated on Scott Hanselman's guide but I am still getting the same error, even after implementing some of his suggested fixes (I don't believe I need all of them) :



  • Added builder.AddUserSecrets<Startup>(); to Startup.

  • Implemented a CustomWebApplicationFactory to set the environment to "Development" - code below has this as "Production" to reproduce the failure.

I also sanity checked against this guide which is more controller focused but since I only care about the response codes at this stage it serves my purpose. I have downloaded the verbose logs and they don't shed any light on the issue.



My code is below:



CustomWebApplicationFactory:



using Microsoft.AspNetCore.Authentication.AzureAD.UI;
using Microsoft.AspNetCore.Authentication.OpenIdConnect;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc.Testing;
using Microsoft.AspNetCore.TestHost;
using Microsoft.Extensions.DependencyInjection;

namespace WebPortal.Int.Tests

/// <summary>
/// Based on https://fullstackmark.com/post/20/painless-integration-testing-with-aspnet-core-web-api
/// </summary>
public class CustomWebApplicationFactory<TStartup> : WebApplicationFactory<Startup> where TStartup : class

public CustomWebApplicationFactory()

protected override void ConfigureWebHost(IWebHostBuilder builder)

builder
.ConfigureTestServices(
services =>

services.Configure(AzureADDefaults.OpenIdScheme, (System.Action<OpenIdConnectOptions>)(o =>

// CookieContainer doesn't allow cookies from other paths
o.CorrelationCookie.Path = "/";
o.NonceCookie.Path = "/";
));

)
.UseEnvironment("Production")
.UseStartup<Startup>();






AuthenticationTests:



using Microsoft.AspNetCore.Mvc.Testing;
using System;
using System.Net.Http;
using System.Threading.Tasks;
using Xunit;

namespace WebPortal.Int.Tests

public class AuthenticationTests : IClassFixture<CustomWebApplicationFactory<Startup>>

private HttpClient _httpClient get;

public AuthenticationTests(CustomWebApplicationFactory<Startup> fixture)

WebApplicationFactoryClientOptions webAppFactoryClientOptions = new WebApplicationFactoryClientOptions

// Disallow redirect so that we can check the following: Status code is redirect and redirect url is login url
// As per https://docs.microsoft.com/en-us/aspnet/core/test/integration-tests?view=aspnetcore-2.2#test-a-secure-endpoint
AllowAutoRedirect = false
;

_httpClient = fixture.CreateClient(webAppFactoryClientOptions);


[Theory]
[InlineData("/")]
[InlineData("/Index")]
[InlineData("/Error")]
public async Task Get_PagesNotRequiringAuthenticationWithoutAuthentication_ReturnsSuccessCode(string url)

// Act
HttpResponseMessage response = await _httpClient.GetAsync(url);

// Assert
try

response.EnsureSuccessStatusCode();

catch (HttpRequestException ex)

Console.WriteLine(ex.Message, ex.InnerException.Message);






Startup:



using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using WebPortal.Authentication;
using WebPortal.Common.ConfigurationOptions;
using WebPortal.DataAccess;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.AzureAD.UI;
using Microsoft.AspNetCore.Authentication.OpenIdConnect;
using Microsoft.AspNetCore.Http;

namespace WebPortal

public class Startup

public Startup(IConfiguration configuration)

Configuration = configuration;


public IConfiguration Configuration get;

// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)

services.Configure<CookiePolicyOptions>(options =>

// This lambda determines whether user consent for non-essential cookies is needed for a given request.
options.CheckConsentNeeded = context => false;
options.MinimumSameSitePolicy = SameSiteMode.None;
);

services.AddOptions<PowerBiSettings>()
.Bind(Configuration.GetSection("PowerBI"))
.ValidateDataAnnotations()
.Validate(o => o.AreSettingsValid());

services.AddOptions<AzureActiveDirectorySettings>()
.Bind(Configuration.GetSection("AzureAd"))
.ValidateDataAnnotations()
.Validate(o => o.AreSettingsValid());

services.AddAuthentication(AzureADDefaults.AuthenticationScheme)
.AddAzureAD(options => Configuration.Bind("AzureAd", options))
.AddCookie();

services.Configure<OpenIdConnectOptions>(AzureADDefaults.OpenIdScheme, options =>

options.Authority = options.Authority + "/v2.0/";
options.TokenValidationParameters.ValidateIssuer = false;
);

services.AddTransient<Authentication.IAuthenticationHandler, AuthenticationHandler>();
services.AddTransient<IReportRepository, ReportRepository>();

services.AddHttpContextAccessor();

services
.AddMvc()
.SetCompatibilityVersion(CompatibilityVersion.Version_2_2)
.AddRazorPagesOptions(options =>

options.Conventions.AuthorizePage("/Reports");
);


// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env)

var builder = new ConfigurationBuilder();

if (env.IsDevelopment())

app.UseDeveloperExceptionPage();

builder.AddUserSecrets<Startup>();

else

app.UseExceptionHandler("/Error");
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();


app.UseHttpsRedirection();
app.UseStaticFiles();

app.UseAuthentication();

app.UseMvc();





Error output:



[xUnit.net 00:00:00.00] xUnit.net VSTest Adapter v2.4.1 (64-bit .NET Core 4.6.27317.07)
[xUnit.net 00:00:01.30] Discovering: WebPortal.Int.Tests
[xUnit.net 00:00:01.40] Discovered: WebPortal.Int.Tests
[xUnit.net 00:00:01.41] Starting: WebPortal.Int.Tests
info: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[0]
User profile is available. Using 'C:UsersVssAdministratorAppDataLocalASP.NETDataProtection-Keys' as key repository and Windows DPAPI to encrypt keys at rest.
info: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[58]
Creating key dd820f09-8139-4d7d-954a-399923660f42 with creation date 2019-03-18 22:13:27Z, activation date 2019-03-18 22:13:27Z, and expiration date 2019-06-16 22:13:27Z.
info: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[39]
Writing data to file 'C:UsersVssAdministratorAppDataLocalASP.NETDataProtection-Keyskey-dd820f09-8139-4d7d-954a-399923660f42.xml'.
info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
Request starting HTTP/2.0 GET http://localhost/Index
warn: Microsoft.AspNetCore.HttpsPolicy.HttpsRedirectionMiddleware[3]
Failed to determine the https port for redirect.
fail: Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware[1]
An unhandled exception has occurred while executing the request.
System.ArgumentNullException: Value cannot be null.
Parameter name: uriString
at System.Uri..ctor(String uriString)
at Microsoft.AspNetCore.Authentication.AzureAD.UI.OpenIdConnectOptionsConfiguration.Configure(String name, OpenIdConnectOptions options)
at Microsoft.Extensions.Options.OptionsFactory`1.Create(String name)
at Microsoft.Extensions.Options.OptionsMonitor`1.<>c__DisplayClass10_0.<Get>b__0()
at System.Lazy`1.ViaFactory(LazyThreadSafetyMode mode)
at System.Lazy`1.ExecutionAndPublication(LazyHelper executionAndPublication, Boolean useDefaultConstructor)
at System.Lazy`1.CreateValue()
at Microsoft.Extensions.Options.OptionsCache`1.GetOrAdd(String name, Func`1 createOptions)
at Microsoft.Extensions.Options.OptionsMonitor`1.Get(String name)
at Microsoft.AspNetCore.Authentication.AuthenticationHandler`1.InitializeAsync(AuthenticationScheme scheme, HttpContext context)
at Microsoft.AspNetCore.Authentication.AuthenticationHandlerProvider.GetHandlerAsync(HttpContext context, String authenticationScheme)
at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context)
at Microsoft.AspNetCore.StaticFiles.StaticFileMiddleware.Invoke(HttpContext context)
at Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware.Invoke(HttpContext context)
fail: Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware[3]
An exception was thrown attempting to execute the error handler.
System.ArgumentNullException: Value cannot be null.
Parameter name: uriString
at System.Uri..ctor(String uriString)
at Microsoft.AspNetCore.Authentication.AzureAD.UI.OpenIdConnectOptionsConfiguration.Configure(String name, OpenIdConnectOptions options)
at Microsoft.Extensions.Options.OptionsFactory`1.Create(String name)
at Microsoft.Extensions.Options.OptionsMonitor`1.<>c__DisplayClass10_0.<Get>b__0()
at System.Lazy`1.ViaFactory(LazyThreadSafetyMode mode)
--- End of stack trace from previous location where exception was thrown ---
at System.Lazy`1.CreateValue()
at Microsoft.Extensions.Options.OptionsCache`1.GetOrAdd(String name, Func`1 createOptions)
at Microsoft.Extensions.Options.OptionsMonitor`1.Get(String name)
at Microsoft.AspNetCore.Authentication.AuthenticationHandler`1.InitializeAsync(AuthenticationScheme scheme, HttpContext context)
at Microsoft.AspNetCore.Authentication.AuthenticationHandlerProvider.GetHandlerAsync(HttpContext context, String authenticationScheme)
at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context)
at Microsoft.AspNetCore.StaticFiles.StaticFileMiddleware.Invoke(HttpContext context)
at Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware.Invoke(HttpContext context)
info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
Request finished in 449.9633ms 500
info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
Request starting HTTP/2.0 GET http://localhost/Error
fail: Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware[1]
An unhandled exception has occurred while executing the request.
System.ArgumentNullException: Value cannot be null.
Parameter name: uriString
at System.Uri..ctor(String uriString)
at Microsoft.AspNetCore.Authentication.AzureAD.UI.OpenIdConnectOptionsConfiguration.Configure(String name, OpenIdConnectOptions options)
at Microsoft.Extensions.Options.OptionsFactory`1.Create(String name)
at Microsoft.Extensions.Options.OptionsMonitor`1.<>c__DisplayClass10_0.<Get>b__0()
at System.Lazy`1.ViaFactory(LazyThreadSafetyMode mode)
--- End of stack trace from previous location where exception was thrown ---
at System.Lazy`1.CreateValue()
at Microsoft.Extensions.Options.OptionsCache`1.GetOrAdd(String name, Func`1 createOptions)
at Microsoft.Extensions.Options.OptionsMonitor`1.Get(String name)
at Microsoft.AspNetCore.Authentication.AuthenticationHandler`1.InitializeAsync(AuthenticationScheme scheme, HttpContext context)
at Microsoft.AspNetCore.Authentication.AuthenticationHandlerProvider.GetHandlerAsync(HttpContext context, String authenticationScheme)
at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context)
at Microsoft.AspNetCore.StaticFiles.StaticFileMiddleware.Invoke(HttpContext context)
at Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware.Invoke(HttpContext context)
[xUnit.net 00:00:02.61] WebPortal.Int.Tests.AuthenticationTests.Get_PagesNotRequiringAuthenticationWithoutAuthentication_ReturnsSuccessCode(url: "/Index") [FAIL]
[xUnit.net 00:00:02.61] System.ArgumentNullException : Value cannot be null.
[xUnit.net 00:00:02.61] Parameter name: uriString
[xUnit.net 00:00:02.61] Stack Trace:
[xUnit.net 00:00:02.61] at System.Uri..ctor(String uriString)
[xUnit.net 00:00:02.61] at Microsoft.AspNetCore.Authentication.AzureAD.UI.OpenIdConnectOptionsConfiguration.Configure(String name, OpenIdConnectOptions options)
[xUnit.net 00:00:02.61] at Microsoft.Extensions.Options.OptionsFactory`1.Create(String name)
[xUnit.net 00:00:02.61] at Microsoft.Extensions.Options.OptionsMonitor`1.<>c__DisplayClass10_0.<Get>b__0()
[xUnit.net 00:00:02.61] at System.Lazy`1.ViaFactory(LazyThreadSafetyMode mode)
[xUnit.net 00:00:02.61] --- End of stack trace from previous location where exception was thrown ---
[xUnit.net 00:00:02.61] at System.Lazy`1.CreateValue()
[xUnit.net 00:00:02.61] at Microsoft.Extensions.Options.OptionsCache`1.GetOrAdd(String name, Func`1 createOptions)
[xUnit.net 00:00:02.61] at Microsoft.Extensions.Options.OptionsMonitor`1.Get(String name)
[xUnit.net 00:00:02.61] at Microsoft.AspNetCore.Authentication.AuthenticationHandler`1.InitializeAsync(AuthenticationScheme scheme, HttpContext context)
[xUnit.net 00:00:02.61] at Microsoft.AspNetCore.Authentication.AuthenticationHandlerProvider.GetHandlerAsync(HttpContext context, String authenticationScheme)
[xUnit.net 00:00:02.61] at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context)
[xUnit.net 00:00:02.61] at Microsoft.AspNetCore.StaticFiles.StaticFileMiddleware.Invoke(HttpContext context)
[xUnit.net 00:00:02.61] at Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware.Invoke(HttpContext context)
[xUnit.net 00:00:02.61] at Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware.Invoke(HttpContext context)
[xUnit.net 00:00:02.61] at Microsoft.AspNetCore.TestHost.HttpContextBuilder.<>c__DisplayClass10_0.<<SendAsync>b__0>d.MoveNext()
[xUnit.net 00:00:02.61] --- End of stack trace from previous location where exception was thrown ---
[xUnit.net 00:00:02.61] at Microsoft.AspNetCore.TestHost.ClientHandler.SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
[xUnit.net 00:00:02.61] at Microsoft.AspNetCore.Mvc.Testing.Handlers.CookieContainerHandler.SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
[xUnit.net 00:00:02.61] at Microsoft.AspNetCore.Mvc.Testing.Handlers.RedirectHandler.SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)[xUnit.net 00:00:02.63] WebPortal.Int.Tests.AuthenticationTests.Get_PagesNotRequiringAuthenticationWithoutAuthentication_ReturnsSuccessCode(url: "/Error") [FAIL]
[xUnit.net 00:00:02.64] WebPortal.Int.Tests.AuthenticationTests.Get_PagesNotRequiringAuthenticationWithoutAuthentication_ReturnsSuccessCode(url: "") [FAIL]

[xUnit.net 00:00:02.61] at System.Net.Http.HttpClient.FinishSendAsyncBuffered(Task`1 sendTask, HttpRequestMessage request, CancellationTokenSource cts, Boolean disposeCts)
[xUnit.net 00:00:02.61] D:a1sWebPortal.Int.TestsAuthenticationTests.cs(24,0): at WebPortal.Int.Tests.AuthenticationTests.Get_PagesNotRequiringAuthenticationWithoutAuthentication_ReturnsSuccessCode(String url)
[xUnit.net 00:00:02.61] --- End of stack trace from previous location where exception was thrown ---


edit



It isn't very clear to me where/why I am getting a null reference because as far as I can tell my OpenIdConnectOptions configuration is correct (and it works with AAD SSO).







c# asp.net-core azure-devops integration-testing






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Mar 20 at 0:14







Matt Stannett

















asked Mar 18 at 2:13









Matt StannettMatt Stannett

512316




512316







  • 2





    Hi, may be stupid question and you have already checked it. But have you tried to move: "builder.AddUserSecrets<Startup>();" outside of env.IsDevelopment() ?

    – Nikolay
    Mar 20 at 8:20







  • 1





    Seeing your stracktrace, I'm pretty sure your question is answered here

    – Jesse de Wit
    Mar 20 at 18:20












  • @Nikolay yes I have tried this thank you.

    – Matt Stannett
    Mar 20 at 20:28











  • @JessedeWit that suggestion didn't fix it my issue but it did put me onto the fact that my AzureAd configuration wasn't being loaded properly during the tests. Hardcoding the values in worked then I realised that I hadn't called .Build() on my ConfigurationBuilder and assigned the value to the Configuration object. This also meant that I moved the code to include the secrets into the Startup constructor.

    – Matt Stannett
    Mar 20 at 20:30












  • 2





    Hi, may be stupid question and you have already checked it. But have you tried to move: "builder.AddUserSecrets<Startup>();" outside of env.IsDevelopment() ?

    – Nikolay
    Mar 20 at 8:20







  • 1





    Seeing your stracktrace, I'm pretty sure your question is answered here

    – Jesse de Wit
    Mar 20 at 18:20












  • @Nikolay yes I have tried this thank you.

    – Matt Stannett
    Mar 20 at 20:28











  • @JessedeWit that suggestion didn't fix it my issue but it did put me onto the fact that my AzureAd configuration wasn't being loaded properly during the tests. Hardcoding the values in worked then I realised that I hadn't called .Build() on my ConfigurationBuilder and assigned the value to the Configuration object. This also meant that I moved the code to include the secrets into the Startup constructor.

    – Matt Stannett
    Mar 20 at 20:30







2




2





Hi, may be stupid question and you have already checked it. But have you tried to move: "builder.AddUserSecrets<Startup>();" outside of env.IsDevelopment() ?

– Nikolay
Mar 20 at 8:20






Hi, may be stupid question and you have already checked it. But have you tried to move: "builder.AddUserSecrets<Startup>();" outside of env.IsDevelopment() ?

– Nikolay
Mar 20 at 8:20





1




1





Seeing your stracktrace, I'm pretty sure your question is answered here

– Jesse de Wit
Mar 20 at 18:20






Seeing your stracktrace, I'm pretty sure your question is answered here

– Jesse de Wit
Mar 20 at 18:20














@Nikolay yes I have tried this thank you.

– Matt Stannett
Mar 20 at 20:28





@Nikolay yes I have tried this thank you.

– Matt Stannett
Mar 20 at 20:28













@JessedeWit that suggestion didn't fix it my issue but it did put me onto the fact that my AzureAd configuration wasn't being loaded properly during the tests. Hardcoding the values in worked then I realised that I hadn't called .Build() on my ConfigurationBuilder and assigned the value to the Configuration object. This also meant that I moved the code to include the secrets into the Startup constructor.

– Matt Stannett
Mar 20 at 20:30





@JessedeWit that suggestion didn't fix it my issue but it did put me onto the fact that my AzureAd configuration wasn't being loaded properly during the tests. Hardcoding the values in worked then I realised that I hadn't called .Build() on my ConfigurationBuilder and assigned the value to the Configuration object. This also meant that I moved the code to include the secrets into the Startup constructor.

– Matt Stannett
Mar 20 at 20:30












2 Answers
2






active

oldest

votes


















4














It turns out that this was because I hadn't called .Build() on my ConfigurationBuilder object that I had created, AND assigned the value to the Configuration field inside the Startup class. This also meant that I moved the code to include the secrets into the Startup constructor.



Even so, my secrets were still not accessible on the build machine (makes sense because they are stored per machine). So I had to add a Command Line task to my build pipeline as well - which uses the dotnet user-secrets set command to add the secrets in that are required for the tests.






share|improve this answer






























    0














    Is it possible that you were missing the AzureAd configuration section from you production settings file? i.e. appsettings.json vs appsettings.Development.json






    share|improve this answer























      Your Answer






      StackExchange.ifUsing("editor", function ()
      StackExchange.using("externalEditor", function ()
      StackExchange.using("snippets", function ()
      StackExchange.snippets.init();
      );
      );
      , "code-snippets");

      StackExchange.ready(function()
      var channelOptions =
      tags: "".split(" "),
      id: "1"
      ;
      initTagRenderer("".split(" "), "".split(" "), channelOptions);

      StackExchange.using("externalEditor", function()
      // Have to fire editor after snippets, if snippets enabled
      if (StackExchange.settings.snippets.snippetsEnabled)
      StackExchange.using("snippets", function()
      createEditor();
      );

      else
      createEditor();

      );

      function createEditor()
      StackExchange.prepareEditor(
      heartbeatType: 'answer',
      autoActivateHeartbeat: false,
      convertImagesToLinks: true,
      noModals: true,
      showLowRepImageUploadWarning: true,
      reputationToPostImages: 10,
      bindNavPrevention: true,
      postfix: "",
      imageUploader:
      brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
      contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
      allowUrls: true
      ,
      onDemand: true,
      discardSelector: ".discard-answer"
      ,immediatelyShowMarkdownHelp:true
      );



      );













      draft saved

      draft discarded


















      StackExchange.ready(
      function ()
      StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f55213911%2fasp-net-core-integration-test-works-locally-but-throws-null-reference-exception%23new-answer', 'question_page');

      );

      Post as a guest















      Required, but never shown

























      2 Answers
      2






      active

      oldest

      votes








      2 Answers
      2






      active

      oldest

      votes









      active

      oldest

      votes






      active

      oldest

      votes









      4














      It turns out that this was because I hadn't called .Build() on my ConfigurationBuilder object that I had created, AND assigned the value to the Configuration field inside the Startup class. This also meant that I moved the code to include the secrets into the Startup constructor.



      Even so, my secrets were still not accessible on the build machine (makes sense because they are stored per machine). So I had to add a Command Line task to my build pipeline as well - which uses the dotnet user-secrets set command to add the secrets in that are required for the tests.






      share|improve this answer



























        4














        It turns out that this was because I hadn't called .Build() on my ConfigurationBuilder object that I had created, AND assigned the value to the Configuration field inside the Startup class. This also meant that I moved the code to include the secrets into the Startup constructor.



        Even so, my secrets were still not accessible on the build machine (makes sense because they are stored per machine). So I had to add a Command Line task to my build pipeline as well - which uses the dotnet user-secrets set command to add the secrets in that are required for the tests.






        share|improve this answer

























          4












          4








          4







          It turns out that this was because I hadn't called .Build() on my ConfigurationBuilder object that I had created, AND assigned the value to the Configuration field inside the Startup class. This also meant that I moved the code to include the secrets into the Startup constructor.



          Even so, my secrets were still not accessible on the build machine (makes sense because they are stored per machine). So I had to add a Command Line task to my build pipeline as well - which uses the dotnet user-secrets set command to add the secrets in that are required for the tests.






          share|improve this answer













          It turns out that this was because I hadn't called .Build() on my ConfigurationBuilder object that I had created, AND assigned the value to the Configuration field inside the Startup class. This also meant that I moved the code to include the secrets into the Startup constructor.



          Even so, my secrets were still not accessible on the build machine (makes sense because they are stored per machine). So I had to add a Command Line task to my build pipeline as well - which uses the dotnet user-secrets set command to add the secrets in that are required for the tests.







          share|improve this answer












          share|improve this answer



          share|improve this answer










          answered Mar 23 at 20:35









          Matt StannettMatt Stannett

          512316




          512316























              0














              Is it possible that you were missing the AzureAd configuration section from you production settings file? i.e. appsettings.json vs appsettings.Development.json






              share|improve this answer



























                0














                Is it possible that you were missing the AzureAd configuration section from you production settings file? i.e. appsettings.json vs appsettings.Development.json






                share|improve this answer

























                  0












                  0








                  0







                  Is it possible that you were missing the AzureAd configuration section from you production settings file? i.e. appsettings.json vs appsettings.Development.json






                  share|improve this answer













                  Is it possible that you were missing the AzureAd configuration section from you production settings file? i.e. appsettings.json vs appsettings.Development.json







                  share|improve this answer












                  share|improve this answer



                  share|improve this answer










                  answered Mar 22 at 19:48









                  Jason G.Jason G.

                  367113




                  367113



























                      draft saved

                      draft discarded
















































                      Thanks for contributing an answer to Stack Overflow!


                      • Please be sure to answer the question. Provide details and share your research!

                      But avoid


                      • Asking for help, clarification, or responding to other answers.

                      • Making statements based on opinion; back them up with references or personal experience.

                      To learn more, see our tips on writing great answers.




                      draft saved


                      draft discarded














                      StackExchange.ready(
                      function ()
                      StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f55213911%2fasp-net-core-integration-test-works-locally-but-throws-null-reference-exception%23new-answer', 'question_page');

                      );

                      Post as a guest















                      Required, but never shown





















































                      Required, but never shown














                      Required, but never shown












                      Required, but never shown







                      Required, but never shown

































                      Required, but never shown














                      Required, but never shown












                      Required, but never shown







                      Required, but never shown







                      Popular posts from this blog

                      SQL error code 1064 with creating Laravel foreign keysForeign key constraints: When to use ON UPDATE and ON DELETEDropping column with foreign key Laravel error: General error: 1025 Error on renameLaravel SQL Can't create tableLaravel Migration foreign key errorLaravel php artisan migrate:refresh giving a syntax errorSQLSTATE[42S01]: Base table or view already exists or Base table or view already exists: 1050 Tableerror in migrating laravel file to xampp serverSyntax error or access violation: 1064:syntax to use near 'unsigned not null, modelName varchar(191) not null, title varchar(191) not nLaravel cannot create new table field in mysqlLaravel 5.7:Last migration creates table but is not registered in the migration table

                      용인 삼성생명 블루밍스 목차 통계 역대 감독 선수단 응원단 경기장 같이 보기 외부 링크 둘러보기 메뉴samsungblueminx.comeh선수 명단용인 삼성생명 블루밍스용인 삼성생명 블루밍스ehsamsungblueminx.comeheheheh

                      155 수학 과학 기타 둘러보기 메뉴eh추가해eh문서를 완성해