How do I validate the DI container in ASP.NET Core

2019-02-08 13:12发布

In my Startup class I use the ConfigureServices(IServiceCollection services) method to set up my service container, using the built-in DI container from Microsoft.Extensions.DependencyInjection.

I want to validate the dependency graph in an unit test to check that all of the services can be constructed, so that I can fix any services missing during unit testing instead of having the app crash at runtime. In previous projects I've used Simple Injector, which has a .Verify() method for the container. But I haven't been able to find anything similar for ASP.NET Core.

Is there any built-in (or at least recommended) way of verifying that the entire dependency graph can be constructed?

(The dumbest way I can think of is something like this, but it will still fail because of the open generics that are injected by the framework itself):

startup.ConfigureServices(serviceCollection);
var provider = serviceCollection.BuildServiceProvider();
foreach (var serviceDescriptor in serviceCollection)
{
    provider.GetService(serviceDescriptor.ServiceType);
}

1条回答
Ridiculous、
2楼-- · 2019-02-08 13:58

To make sure your ASP.NET Core application works as expected and all dependencies are injected right, you should use Integration testing in ASP.NET Core. This way you can initialize TestServer with the same Startup class, so it causes all dependencies to be injected (no mocks or similar stubs) and test your application using the exposed routes/URLs/paths.

Integration test for the default root URL might look like this:

public class PrimeWebDefaultRequestShould
{
    private readonly TestServer _server;
    private readonly HttpClient _client;
    public PrimeWebDefaultRequestShould()
    {
        // Arrange
        _server = new TestServer(new WebHostBuilder().UseStartup<Startup>());
        _client = _server.CreateClient();
    }

    [Fact]
    public async Task ReturnHelloWorld()
    {
        // Act
        var response = await _client.GetAsync("/");
        response.EnsureSuccessStatusCode();

        var responseString = await response.Content.ReadAsStringAsync();

        // Assert
        Assert.Equal("Hello World!", responseString);
    }
}

If you need to retrieve specific services injected via DI you cal always do it this way:

var service = _server.Host.Services.GetService(typeof(IYourService));
查看更多
登录 后发表回答