Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to override DI registration from other container in ASP.NET Core integration test

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?

like image 699
Frost He Avatar asked Aug 15 '18 09:08

Frost He


People also ask

What is IWebHostBuilder in .NET core?

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.

What is WebApplicationFactory?

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 in asp net core?

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.


1 Answers

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:

  • WebHost specific ConfigureServices
  • Startup class ConfigureServices
  • Startup class ConfigureContainer

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:

  • Move the registration you need to override out of ConfigureContainer and into one of the ConfigureServices methods, using the Microsoft registration language instead of native Autofac.
  • Perform the override some other way like using an ASPNETCORE_ENVIRONMENT setting of Test and providing a ConfigureTestContainer method. (Examples of environment specific registration methods are in the docs.)
like image 186
Travis Illig Avatar answered Sep 28 '22 05:09

Travis Illig