I have the following registration in asp.net core startup.cs file:
public void ConfigureContainer(ContainerBuilder builder)
{
builder.RegisterType<UserService>().As<IUserService>();
}
This is to configure the Autofac container. And I have another integration test project where I have a CustomWebApplicationFactory class and I'm trying to replace the implementation of IUserService interface.
protected override void ConfigureWebHost(IWebHostBuilder builder)
{
builder.ConfigureTestServices(services =>
{
services.AddSingleton<IUserService, TestUsersService>();
});
}
It seems not work when I debug the test project and the implementation of IUserService is still UserService.
I tried registering UserService directly in Startup.ConfigureServices method with ASP.NET Core built-in IServiceCollection and it worked when debugging:
services.AddSingleton<IUserService, UserService>();
So, how can I fix the problem when I use Autofac as the IoC container and the integration test project will work properly as I expect?
UseIIS(IWebHostBuilder) Configures the port and base path the server should listen on when running behind AspNetCoreModule. The app will also be configured to capture startup errors. UseIISIntegration(IWebHostBuilder) Configures the port and base path the server should listen on when running behind AspNetCoreModule.
WebApplicationFactory<TEntryPoint> is used to create a TestServer for the integration tests. TEntryPoint is the entry point class of the SUT, usually the Startup class.
What is DI Container. A DI Container is a framework to create dependencies and inject them automatically when required. It automatically creates objects based on the request and injects them when required. DI Container helps us to manage dependencies within the application in a simple and easy way.
You are likely running into an order of operations problem. In general, last in wins. That goes for Autofac and for the base Microsoft DI container.
Assuming you've read through the docs on Autofac ASP.NET Core integration you'll see that when ConfigureContainer
is in place the order of operations is roughly:
When adding ConfigureTestServices in place, it looks like (though I haven't stepped through) it runs after the WebHost and Startup class ConfigureServices... but it's still running before ConfigureContainer.
This would be easy enough to test - create a service interface with three different implementations. Register a different implementation at each level. Resolve the interface in a controller. Which one did you get? That was the last one to run. Now remove that registration from the app and try again. What's the next one you get? That's the second to the last one. And so on.
Autofac takes a pre-built IServicesCollection
and cycles through it, adding that to the native Autofac container. Once that's happened, it doesn't matter if you modify the collection. Autofac has no control over the order of the execution of the startup mechanism in ASP.NET Core; it just knows that ASP.NET Core says, "Here's the final service collection to go ahead and import!" If that's not happening at the right stage, you'll have to do one of two things:
ConfigureContainer
and into one of the ConfigureServices
methods, using the Microsoft registration language instead of native Autofac.ASPNETCORE_ENVIRONMENT
setting of Test
and providing a ConfigureTestContainer
method. (Examples of environment specific registration methods are in the docs.)If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With