-
Notifications
You must be signed in to change notification settings - Fork 209
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
.NET 6 WebApplicationFactory test throws System.InvalidOperationException : The entry point exited without ever building an IHost. #289
Comments
I have the same. Really annoying. |
Thanks for the report! Someone will need to set up "break on all exceptions", or step through the test in a debugger to narrow it down. I assembled a test project using the sample above, without Swashbuckle and my test can instantiate the test host and resolve (Another approach might be to try dropping the Swashbuckle-related config from Program.cs and see whether you still hit an issue.) |
After removing Swashbuckle from the project issue still occurs. |
Stack trace looks like this:
|
Thanks @pikoscielniak; does "Break on all exceptions" show anything up? |
It's really strange. When I run tests in debug all tests pass. |
The tests also pass when I run them with coverage. |
Probably I know why tests pass in debug or in coverage because than they are executed by IDE one after another, but problem only happens when tests are run parallel. |
I can confirm that the problem happens only when tests are run in parallel. When I run test with the config:
they all pass, but unfortunately it's not a solution at my case. I strongly need run tests parallelly. |
Does the issue persist if you switch from |
Changing Serilog initialization in
to:
solved the problem. |
@pikoscielniak thanks for helping to track it down. Freezing is a stateful operation: Not sure how best to avoid this in testing.. 🤔 |
@nblumhardt does using |
https://nblumhardt.com/2020/10/bootstrap-logger/#why-cant-we-just-do-both has some info on the problems |
Just adding another voice here that we're also seeing this exception in parallel unit tests when using |
Not sure if this is the right place to make a comment, but I think I've just hit this condition - but not when unit testing. At least in my case, I am adding a
However, when I use the provider to resolve a service, there seems to be a reentry going on somewhere as it cycles back to the I'm unsure if it's a Serilog issue or a NET6 / AspNetCore issue. |
Workaround with logger set did not work for me.
|
I'm also having the same issue when tests are run in parallel. I'm using a wrapper library to create the logger, which internally calls the |
@span @MichaelDeutschCoding sounds like you're hitting something else; if you're sure it's Serilog-related, could you please post a new issue and include as much detail as possible? Thanks! |
I can confirm my issues were not only Serilog related and they are now resolved. I had two issues. I did feel the need to post here though, since Google search result were sparse on the error message.
|
Does anyone have a solution please? |
A switch from |
Same issue here. This is an ugly issue IMO because if you try and do everything right by following the Serilog docs and use Maybe the Serilog docs could be improved to warn of this? IE:
Or maybe there is a way for someone much smarter than me to maker a change in |
I ran into this today and settled on the following workaround. Step 1 : inject a setting during the test server bootstrap public class CustomWebAppFactory
: WebApplicationFactory<Your.Program>
{
protected override void ConfigureWebHost(IWebHostBuilder builder)
{
builder.UseSetting("integrationTest", "true");
...
} Step 2: pull out the arg and conditionally build your loggers public static Serilog.ILogger CreateIntegrationTestLogger()
=> new LoggerConfiguration()
.WriteTo.Console()
.CreateLogger();
public static Serilog.ILogger CreateBootstrapLogger()
=> new LoggerConfiguration()
.WriteTo.Console()
.CreateBootstrapLogger();
public static void Main(string[] args)
{
var isIntegrationTest = args.Contains("--integrationTest=true");
Log.Logger = isIntegrationTest ? CreateIntegrationTestLogger() : CreateBootstrapLogger();
...
} Another option would be to use |
Is it too dirty? The problem is that the host creation is called multiple time during test. I am not sure If it will influence in production.
|
Are we obligated to use using Serilog;
using var log = new LoggerConfiguration()
.WriteTo.Console()
.CreateLogger();
try
{
var builder = WebApplication.CreateBuilder(args);
builder.Host.UseSerilog((ctx, sp, conf) => conf.ReadFrom.Configuration(ctx.Configuration)));
// builder configuration omitted
var app = builder.Build();
// app configuration omitted
app.Run();
}
catch (Exception ex)
{
log.Fatal(ex, "An unhandled exception occurred during bootstrapping");
}
public partial class Program { } |
Also LGTM, @gritcsenko, if you're not using |
@nblumhardt Coming in as another mildly annoyed person who followed both Serilog and MSFT's documentation for appropriately using Serilog and E2E testing w/ WebApplicationFactory, and after a couple days of trial and error, stumbled across parallelization as the culprit and thus this issue. It would be great to either see a resolution or perhaps an edit to the documentation for |
…und it by not using BootstrapLogger. We do not need it anyway
* Re-factor. GetFile query was excessively complex so split up part into separate query. Also updated FileEntity to use Actor entity consistenly. * Added application code for deleting file * Added Hangfire support * Added deletion after everyone has confirmed download * Added code to add service owner to database * Added corresponding field to File * Add logic to trigger Hangfire jobs for deleting file on all confirmed downloaded and file initialized * Removed unused return value * Formatting * Consolidated naming * Formatting * Fix test data * Known issue in Serilog: serilog/serilog-aspnetcore#289 and we get around it by not using BootstrapLogger. We do not need it anyway * Try with joining the repeatable migration sripts together. Seems one fails to run if it is dependent on the other one when in a brand new environment. Should find better way to split up in more test scripts if we get big script. * Hangfire in memory during tests to avoid issues with concurrent initialization
If following the approach suggested by gritcsenko above, is there a way to do the equivalent of |
Another workaround: Derive from WebApplicationFactory if you aren't already, and add the following: private static readonly object _lock = new();
/// <summary>
/// There is a problem with using Serilog's "CreateBootstrapLogger" when trying to initialize a web host.
/// This is because in tests, multiple hosts are created in parallel, and Serilog's static logger is not thread-safe.
/// The way around this without touching the host code is to lock the creation of the host to a single thread at a time.
/// </summary>
/// <param name="builder"></param>
/// <returns></returns>
protected override IHost CreateHost(IHostBuilder builder)
{
lock (_lock)
return base.CreateHost(builder);
} This will make sure the host will be initialized in a single thread. Short of yanking out the BootstrapLogger, that's the only minimally-invasive approach I've found. |
Great solution, thanks @vvdb-architecture! 👍 |
Description
When I have Serilog configured on my Program.cs and if I run more than one test that uses WebApplicationFactory I get an exception thrown
System.InvalidOperationException : The entry point exited without ever building an IHost.
accessing the application factory services.Reproduction
Program.cs
appsettings.json
:TestApplication.cs
:SwaggerTest.cs
:Expected behavior
Tests pass, and does not throw calling application.Services
Relevant package, tooling and runtime versions
dotnet --version
:Additional context
The tests pass if I comment out the line
builder.Host.UseSerilog((ctx, lc) => lc.ReadFrom.Configuration(ctx.Configuration));
fromProgram.cs
.The text was updated successfully, but these errors were encountered: