Repository: HangfireIO/Hangfire

Issue #821: Use of GlobalConfiguration and static fields makes testing more difficult
Created: 2017-02-28T04:31:56Z
We have a number of cross cutting tests that involve our DI container (Autofac) and Hangfire. When testing these sub-systems. I am trying to stand up our container with new instances of Hangfire for each test.
Currently lines like this one: Static interlocked check to avoid additional execution
Makes tearing down Hangfire really tricky and I'm having to replace Service Descriptors in the IServiceCollection to make sure Hangfire is bound to the correct Activator and Logging instances for each test.

Duplicate issue #1200: Console is already initialized
Created: 2018-06-06T14:32:30Z
I am setting up test project and when I am running my tests I get below error.
System.InvalidOperationException : Console is already initialized
   at Hangfire.Console.GlobalConfigurationExtensions.UseConsole(IGlobalConfiguration configuration, ConsoleOptions options)
   at Service.Content.Reverter.WindowsService.Infrastructure.Hangfire.HangfireConfiguration.ConfigureHangfireDashboardServer(IApplicationBuilder app)
   at Service.Content.Reverter.WindowsService.Startup.Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at Microsoft.AspNetCore.Hosting.ConventionBasedStartup.Configure(IApplicationBuilder app)
   at Microsoft.AspNetCore.Hosting.Internal.AutoRequestServicesStartupFilter.<>c__DisplayClass0_0.<Configure>b__0(IApplicationBuilder builder)
   at Microsoft.AspNetCore.Hosting.Internal.WebHost.BuildApplication()
   at Microsoft.AspNetCore.Hosting.Internal.WebHost.<StartAsync>d__26.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Microsoft.AspNetCore.TestHost.TestServer..ctor(IWebHostBuilder builder, IFeatureCollection featureCollection)
   at Microsoft.AspNetCore.TestHost.TestServer..ctor(IWebHostBuilder builder)
   at Bbc.Ww.WindowsService.IntegrationTests.API.WebserverTestsBase.BeforeEachTestBaseSetup() in C:\Projects\service-content-reverter\src\WindowsService.IntegrationTests\API\ProcessStatusControllerTests.cs:line 80

Running test with root C:\Projects\service-content-reverter\src\WindowsService
Application startup exception: System.InvalidOperationException: Console is already initialized
   at Hangfire.Console.GlobalConfigurationExtensions.UseConsole(IGlobalConfiguration configuration, ConsoleOptions options)
   at Service.Content.Reverter.WindowsService.Infrastructure.Hangfire.HangfireConfiguration.ConfigureHangfireDashboardServer(IApplicationBuilder app)
   at Service.Content.Reverter.WindowsService.Startup.Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at Microsoft.AspNetCore.Hosting.ConventionBasedStartup.Configure(IApplicationBuilder app)
   at Microsoft.AspNetCore.Hosting.Internal.AutoRequestServicesStartupFilter.<>c__DisplayClass0_0.<Configure>b__0(IApplicationBuilder builder)
   at Microsoft.AspNetCore.Hosting.Internal.WebHost.BuildApplication()
crit: Microsoft.AspNetCore.Hosting.Internal.WebHost[6]
      Application startup exception
System.InvalidOperationException: Console is already initialized
   at Hangfire.Console.GlobalConfigurationExtensions.UseConsole(IGlobalConfiguration configuration, ConsoleOptions options)
   at Service.Content.Reverter.WindowsService.Infrastructure.Hangfire.HangfireConfiguration.ConfigureHangfireDashboardServer(IApplicationBuilder app)
   at Service.Content.Reverter.WindowsService.Startup.Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at Microsoft.AspNetCore.Hosting.ConventionBasedStartup.Configure(IApplicationBuilder app)
   at Microsoft.AspNetCore.Hosting.Internal.AutoRequestServicesStartupFilter.<>c__DisplayClass0_0.<Configure>b__0(IApplicationBuilder builder)
   at Microsoft.AspNetCore.Hosting.Internal.WebHost.BuildApplication()

I know the issue lies in below code:
GlobalConfiguration.Configuration.UseConsole();
This error message is added in 1.3.10
+            if (DashboardRoutes.Routes.Contains("/console/([0-9a-f]{11}.+)"))
+                throw new InvalidOperationException("Console is already initialized");

but not sure what is elegant way to stop calling UseConsole() more than once. This code is written as part of HangFireConfiguration class. can we clear HangFire GlobalConfiguration?

Closing comment (2021-09-25T15:44:03Z): Hangfire and its extensions, as useful as they are, do rely too much on static state in GlobalConfiguration.Configuration, JobStorage.Current, JobActivator.Current, causing problems when multiple IServiceCollections are initialized. The actual issue is tracked in #821, I believe.