-
Notifications
You must be signed in to change notification settings - Fork 10.3k
WebApplication does not observe changes made with WebApplicationFactory<T> in tests #33876
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
Comments
I'm still having a dig around trying to work out what's going on with this, but I think it might be to do with the fact that |
These issues are related to WebApplicationBuilder/WebApplication and might be related to #33082 but @halter73 might be able to pin point as he's working on this area right now. The same logic works if you use top level statements with the HostBuilder directly: Host.CreateDefaultBuilder()
.ConfigureWebHostDefaults(builder =>
{
builder.Configure(app =>
{
app.UseStaticFiles();
app.UseRouting();
app.UseEndpoints(endpoints =>
{
endpoints.MapGet("/api", (IConfiguration config, IHostEnvironment environment, IServiceProvider serviceProvider) =>
{
return new
{
configurations = serviceProvider.GetServices<IConfiguration>().Count(),
environment = environment.EnvironmentName,
message = config["Message"],
value = config["Value"],
};
});
});
});
})
.Build()
.Run(); I had a make a couple of tweaks to your tests but they all passed. |
I think I'll stop banging my head against this one for now and see what Stephen makes of it. |
@martincostello keep finding these bugs, they are super helpful! |
I think I've gotten as far as I can with my sample app for minimal actions that's how I've flushed out the various issues I've logged. I'll come back to it again when there's fixes available and/or later official preview builds released. The changes are here if it helps you with any debugging/investigation: martincostello/dotnet-minimal-api-integration-testing#2 Two outstanding issues I've got that I've not logged yet as they're only apparent after several layers of workarounds and hacks:
|
Thanks for contacting us. We're moving this issue to the |
Add unit tests that replicate dotnet#33876 and dotnet#33889.
@martincostello I think I've found the root cause here. Have you looked at filing those other issues? |
Not yet. Because there's been the other issues around configuration and also I've spotted other PRs related to fixing issues with the hosting environment's content root I wasn't sure if they were just further side-effects of the configuration being incorrect in the final running app. I was going to circle back to them once there was some thought that the configuration issues should have been resolved, as then either those would resolve themselves, or they'd turn out to be additional issues. |
One realization though is that you won't be able to change configuration values if they are read directly before Build: using Microsoft.EntityFrameworkCore;
var builder = WebApplication.CreateBuilder(args);
// This reads configuration values before there's a chance to mutate them by the test
var connectionString = builder.Configuration.GetConnectionString("Todos") ?? "Data Source=Todos.db";
builder.Services.AddDbContext<TodoDbContext>(o => o.UseSqlite(connectionString)); VS using Microsoft.EntityFrameworkCore;
var builder = WebApplication.CreateBuilder(args);
// This reads configuration values much later, and they can be observed by tests
builder.Services.AddDbContext<TodoDbContext>(o => o.UseSqlite(builder.Configuration.GetConnectionString("Todos") ?? "Data Source=Todos.db")); @JunTaoLuo @DamianEdwards this is relevant because the new provider focused overloads we added to EF take the connection string as a parameter value directly and won't be observable by tests. |
@martincostello Re-running your tests with my changes I had to make some test changes but only one test fails now, the |
Ah cool - I wonder if that might be related to the issue with the Razor Pages 404 thing I mentioned in the comment further above? |
It's not, I've figured out that issue as well. The last piece of the puzzle is that we need to follow the same pattern for the |
Interesting, so it's kinda all different cases of the same class of issue? |
Yep. Essentially, the WebApplicationBuilder is trying to be the source of truth for IConfiguration, the IServiceCollection, and the IWebHostEnvironment. The problem is that internally, it creates a HostBuilder which creates its own |
So I think is a general problem using this new var builder = WebApplication.CreateBuilder(args);
if (builder.Environment.IsEnvironment("Testing"))
{
builder.Services.AddSingleton<IThing, MyTestThing>();
}
else
{
builder.Services.AddSingleton<IThing, MyProductionThing>();
}
var app = builder.Build(); // The WebApplicationFactory<T> plugs in here
app.MapGet("/", () => "Hello World");
app.Run();
interface IThing { }
class MyTestThing : IThing { }
class MyProductionThing : IThing { } If the WebApplicationFactory tries to change the environment to to Testing here, it wouldn't work because it's too late and there's no hook that runs early enough. cc @halter73 |
@davidfowl I've pulled this change into my test app with Overall I've got these three issues left with my test app with the latest RC1 build:
|
@davidfowl The changes you made in #34794 have fixed issues 2 and 3 above 🥳 |
Describe the bug
When using
WebApplicationFactory
/WebApplication
in conjunction withWebApplicationFactory<T>
for integration tests, theWebApplication
created byWebApplicationFactory
does not observe configuration changes made to theIWebHostBuilder
byWebApplicationFactory<T>
.First, if the configuration is changed using
ConfigureAppConfiguration()
, the changes are not visible in theIConfiguration
resolved by theWebApplication
. This applies to adding new sources as well as clearing the existing sources. In both cases, the original configuration remains with the built application, and the changes applied for the tests by theWebApplicationFactory<T>
are not visible to the application.Calling
serviceProvider.GetServices<IConfiguration>().Count()
within the application returns a value of2
. It appears that both twoIConfiguration
implementations, one for the web host and another forWebApplication
are registered with the service provider, with theWebApplication
one being resolved by calls toGetService<IConfiguration>()
meaning that the changes are not observed.This can be worked around by using
ConfigureServices()
to clear the duplicate registration to leave the one required by the tests:Secondly, changes to the content root are not observed by the application. If
UseContentRoot()
is used to change the directory to serve content byWebApplicationFactory<T>
, the change is not visible to theWebApplication
instance, which continues to use the path associated with where the test process was launched from.This causes static content to not be found when requested.
To Reproduce
An application that reproduces this issue is available at https://github.com/martincostello/WebApplicationFactory-Config-Issues. To reproduce the issue:
https://github.com/martincostello/WebApplicationFactory-Config-Issues.git
build.ps1
The following test failures are then observed:
Can_Override_Configuration
test fails because the original value ofValue
is used from configuration ("a"
) instead of the one overridden by the tests ("b"
).Can_Override_ContentRoot
tests fails because a 404 is returned due to the application being unable to find thetest.txt
file to serve the static content.Can_Remove_Configuration
test fails because the original value ofValue
is used from configuration ("a"
) instead of an empty value of""
because all of the configuration sources were removed.Running the application under the debugger in Visual Studio 2022 and requesting the
/api
or/test.txt
resources in a browser show the application works as expected when run outside of the test project.Similarly the
Application_Returns_Defaults
test also works correctly as no overrides are provided.Further technical details
6.0.100-preview.6.21324.1
(I tried to use the latest preview 7 build but had issues running it in Visual Studio 2022)The text was updated successfully, but these errors were encountered: