Reputation:
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>());
Upvotes: 1
Views: 1748
Reputation: 8498
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.
Of course, it's also possible to just store the reference to ServiceCollection
in a variable/field, and enumerate the services whenever necessary.
Upvotes: 1
Reputation: 3367
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, e.g. with moq.
Upvotes: 0