简体   繁体   中英

How to get all the Services from Startup.cs

How do I obtain all the services after StartupClass has run?

We have a Startup Configure Services class which runs multiple dependency injection.

 serviceCollection.AddScoped<IDepartmentRepository, DepartmentRepository>();
 serviceCollection.AddScoped<IDepartmentAppService, DepartmentAppService>();

Team is using Xunit Test Project and wants to grab all the Service collection list for Xunit.

Need services from this below:

new WebHostBuilder()
            .UseContentRoot("C:\\Test\\Test.WebAPI")
            .UseEnvironment("Development")
            .UseConfiguration(new ConfigurationBuilder()
                .SetBasePath("C:\\Test\\Test.WebAPI")
                .AddJsonFile("appsettings.json")
                .Build()).UseStartup<Startup>());

Services in ServiceCollection are represented by the ServiceDescriptor class. You can get a list of all service descriptors by chaining a ConfigureTestServices method to your WebHostBuilder (you have to install Microsoft.AspNetCore.TestHost package)

using Microsoft.AspNetCore.TestHost;

....

IWebHost CreateWebHost(out ServiceDescriptor[] allServices)
{
    ServiceDescriptor[] grabbedServices = null;

    var host = new WebHostBuilder()
        // ... other stuff ...
        .UseStartup<Startup>()
        // add the following call:
        .ConfigureTestServices(services => {
            // copy all service descriptors
            grabbedServices = services.ToArray(); 
        })
        // build the host now to trigger the above chain
        .Build();

    allServices = grabbedServices;
    return host;
}

It is then convenient to use like this:

[Fact]
public void TestSomething()
{
    // arrange

    var host = CreateWebHost(out var services);
    // ... do something with the services

    // act
    // assert    
}

The reason we have to use ConfigureTestServices (and not ConfigureServices ) is that ConfigureServices is always invoked before the methods in the Startup class, whereas ConfigureTestServices is invoked afterward.

UPDATE

Of course, it's also possible to just store the reference to ServiceCollection in a variable/field, and enumerate the services whenever necessary.

So I understood your question that you want to test you services and have problems with loading them in test project. I'd say you don't need to. In unit tests every time you test a single service. This service you instantiate directly:

var target= new ServiceToTest();

So you reference your testED project from your test project. In case your implementation is internal, add to your testED project an AssemblyInfo.cs file and put the following inside:

[assembly: InternalsVisibleTo("MyTestProject")]

Whenever you test your MyServiceToTest1, in case it has a dependecy to MyServiceTest2, you don't have to load or instantiate MyServiceTest2. Instead you mock it, eg with moq .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM