-
Notifications
You must be signed in to change notification settings - Fork 10.5k
Description
Is there an existing issue for this?
- I have searched the existing issues
Describe the bug
Description:
When using Microsoft.AspNetCore.TestHost.TestServer in unit tests for an ASP.NET Core project, I have encountered unexpected behavior. In the test setup, I create a TestServer instance where the startup class is provided via a factory function through WebHostBuilder.UseStartup(Func<WebHostBuilderContext, Startup> startupFactory).
In this configuration, my MVC controllers are not being properly loaded, resulting in 404 errors when trying to hit those controller routes. However, the same startup factory function works correctly when used within WebHostBuilder.ConfigureWebHostDefaults in the application's main entry point (Program.cs). In this latter scenario, the application runs as expected and all controllers are correctly loaded and reachable.
Interestingly, the ConfigureServices and Configure methods in the Startup class are still being called as expected during the unit tests.
Here's a simplified code snippet from my unit tests:
Func<WebHostBuilderContext, Startup> startupFactory = context =>
{
var mockService = new Mock<IMyService>();
var startup = new Startup(context.Configuration, mockService.Object);
return startup;
};
var server = new TestServer(new WebHostBuilder()
#if DEBUG
.UseEnvironment(Environments.Development)
#else
.UseEnvironment(Environments.Production)
#endif
.UseStartup<Startup>(startupFactory));
var client = server.CreateClient();
Workaround:
To bypass this issue, I implemented a workaround by creating two constructors for the Startup class. The default constructor creates an instance of the default service, and the overloaded constructor accepts the service as a parameter, which can be a mock for unit tests:
public class Startup
{
private readonly IMyService myService;
public Startup(IConfiguration configuration)
: this(configuration, new TestMockMyService())
{
}
public Startup(IConfiguration configuration, IMyService myService)
{
// Startup logic...
}
public void ConfigureServices(IServiceCollection services)
{
// This method is being called as expected
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
// This method is being called as expected
}
}
While this workaround allows me to inject mock services during unit tests, it seems less than ideal as it requires modifying the Startup class with additional constructors, which may not always be desirable or possible.
Expected Behavior:
I expect the TestServer to load my controllers correctly when a startup factory function is provided, just like it does when running the application.
Actual Behavior:
When running unit tests, the controllers are not being loaded, even though ConfigureServices and Configure methods are being called. However, when running the application, the controllers are correctly loaded.
Expected Behavior
No response
Steps To Reproduce
No response
Exceptions (if any)
No response
.NET Version
7.0.306
Anything else?
Related