ServiceProviderCache adds more and more IServiceProviders when running integration tests

See original GitHub issue

When running .NET Core integration tests using WebApplicationFactory the ServiceProviderCache seems to add more and more IServiceProviders for each test until the limit of twenty is reached. By then a warning is logged or an error is thrown depending on how it’s configured.

If the DbContext is configured to throw an error, this is the exception thrown:

Exception message:
System.InvalidOperationException: Error generated for warning 'Microsoft.EntityFrameworkCore.Infrastructure.ManyServiceProvidersCreatedWarning: More than twenty 'IServiceProvider' instances have been created for internal use by Entity Framework. This is commonly caused by injection of a new singleton service instance into every DbContext instance. For example, calling UseLoggerFactory passing in a new instance each time--see https://go.microsoft.com/fwlink/?linkid=869049 for more details. Consider reviewing calls on 'DbContextOptionsBuilder' that may require new service providers to be built.'. This exception can be suppressed or logged by passing event ID 'CoreEventId.ManyServiceProvidersCreatedWarning' to the 'ConfigureWarnings' method in 'DbContext.OnConfiguring' or 'AddDbContext'.
Stack trace:
at Microsoft.EntityFrameworkCore.Diagnostics.EventDefinition.Log[TLoggerCategory](IDiagnosticsLogger`1 logger, WarningBehavior warningBehavior, Exception exception)
   at Microsoft.EntityFrameworkCore.Internal.CoreLoggerExtensions.ManyServiceProvidersCreatedWarning(IDiagnosticsLogger`1 diagnostics, ICollection`1 serviceProviders)
   at Microsoft.EntityFrameworkCore.Internal.ServiceProviderCache.<>c__DisplayClass4_0.<GetOrAdd>b__2(Int64 k)
   at System.Collections.Concurrent.ConcurrentDictionary`2.GetOrAdd(TKey key, Func`2 valueFactory)
   at Microsoft.EntityFrameworkCore.Internal.ServiceProviderCache.GetOrAdd(IDbContextOptions options, Boolean providerRequired)
   at Microsoft.EntityFrameworkCore.DbContext.get_InternalServiceProvider()
   at Microsoft.EntityFrameworkCore.DbContext.get_DbContextDependencies()
   at Microsoft.EntityFrameworkCore.DbContext.Microsoft.EntityFrameworkCore.Internal.IDbContextDependencies.get_EntityFinderFactory()
   at Microsoft.EntityFrameworkCore.Internal.InternalDbSet`1.get_Finder()
   at Microsoft.EntityFrameworkCore.Internal.InternalDbSet`1.FindAsync(Object[] keyValues)

Steps to reproduce

https://github.com/mlassbo/ServiceProviderCacheProblem

Further technical details

EF Core version: 2.2.4 Database Provider: Microsoft.EntityFrameworkCore.InMemory Operating system: Windows 10 IDE: Visual Studio 2019 16.1.3

Issue Analytics

  • State:closed
  • Created 4 years ago
  • Reactions:1
  • Comments:16 (9 by maintainers)

github_iconTop GitHub Comments

3reactions
ChristopherHawscommented, Nov 2, 2019

I have run into this issue as well when running integration tests with the InMemory database provider. I tried to use EnableServiceProviderCaching(false) but found that my tests took over 4 min to run (compared to 40 seconds in EF Core 2.2). I was able to just follow the info in the error to disable to ignore the warning/error and all my tests still work and they run in around 45 seconds like they did in v2.2.

.ConfigureWarnings(x =>
{
    x.Ignore(CoreEventId.ManyServiceProvidersCreatedWarning);
})
3reactions
ajcvickerscommented, Jul 1, 2019

The issue here is that each test is effectively spinning up a completely new web app. This means that services we get from ASP.NET are different every test, which in turn means a new internal service provider for every test.

@mlassbo The current workarounds is to manage the internal service provider manually using DbContextOptionsBuilder.UseInternalServiceProvider. However, it’s also worth mentioning that building and throwing away so much for each test could end up being very slow. This is both because setting everything up is a lot of work, and also because the caching that is set up is usually very important for good perf.

Notes for triage:

Things should be better in 3.0, since we don’t need to build a new service provider for a new ILoggerFactory, and we don’t depend on IMemoryCache anymore. It would be useful to know if there are other services that can cause this–possibly IConfiguration for example.

The workaround for 3.0 is also easier, since we added options.EnableServiceProviderCaching(false).

Read more comments on GitHub >

github_iconTop Results From Across the Web

Integration tests in ASP.NET Core
Integration tests confirm that two or more app components work together to produce an expected result, possibly including every component ...
Read more >
c# - Integration test with WebApplicationFactory fails ...
When I run the test, I get the following exception thrown. System.ObjectDisposedException : Cannot access a disposed object.
Read more >
A Better Story for Asp.Net Core Integration Testing | nance.io
The test runs inside a transaction that gets rolled back when the test completes. This allows other tests to assume the database is...
Read more >
Integration Testing with ASP.NET Core 3.1 - Adam Storr
Investigating how to write integration tests while swapping out dependencies with mocked instances using Moq. Published on 23 December 2019.
Read more >
ASP.NET Core Dependency Injection - Steve Gordon
In this post, I explain what an IServiceProvider is and how it can be created and later used to resolve dependencies in ASP.NET...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found