Search code examples
c#.netasp.net-coredependency-injectionnunit-3.0

assert that a service has been injected as scoped service


I am writing a unit test for the following extension method:

public static void AddMyServices(this IServiceCollection services)
{
    services.AddScoped<IServiceA, ServiceA>();
}

Here is what I have to confirm the ServiceA has been injected.

[Test]
public void Should_Resolve_ServiceA() {
    // Arrange
    var services = new ServiceCollection();

    // Act
    services.AddMyServices();
    var serviceProvider = services.BuildServiceProvider();
    var actual = serviceProvider.GetService<IServiceA>();

    // Assert
    Assert.IsNotNull(actual);        
}
        

The test above did ensure the service has been injected. However, services.AddSingleton and services.AddTransient also pass the test.

Is there a solution to get only the scoped injected services so I can ensure it has been injected the correct way?

I am aware that for the simplified example above, I can create a stub for IServiceCollection and check the ReceivedCalls on the stub method. However, I am trying to avoid doing that because I have a lot of AddScope statements in my real extension method and part of the purpose of the unit test above is to ensure all dependencies of a specific service have been injected. So GetService<T> is the preferred way to do the testing.


Solution

  • Once the service is added in the ServiceCollection, you should be able to get back the ServiceDescriptor to verify the service scope. Note that ServiceCollection is an IEnumerable<ServiceDescriptor>. So you can check it like this:

    // Assert
    Assert.AreEqual(services.FirstOrDefault(e => e.ServiceType == typeof(IServiceA))?.Lifetime, ServiceLifetime.Scoped);
    

    You don't need to build the service provider from the service collection. Note that the code above would fail as well if the IServiceA is not registered. That depends on your requirement, you can modify the code as you want. I've just shown the main idea.