Skip to content

Strange exceptions when using AutoMock w/ AddDbContext #49

Description

@cyungmann

Describe the Bug

Get exceptions when using AutoMock w/ AddDbContext upon trying to resolve the DbContext class.

Steps to Reproduce

Download and run AutoMockTest.zip

If you switch the order of calling WorksAsync and DoesNotWorkAsync in Program.cs so that WorksAsync comes first, things suddenly and unexpectedly start working for both methods. If you only call WorksAsync things also work.

Program.cs

using Autofac;
using Autofac.Extensions.DependencyInjection;
using Autofac.Extras.Moq;
using AutoMockTest;
using Microsoft.Data.Sqlite;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;

await DoesNotWorkAsync();
await WorksAsync();

static async Task WorksAsync()
{
    await using var conn = new SqliteConnection(new SqliteConnectionStringBuilder
    {
        DataSource = ":memory:",
    }.ConnectionString);
    await conn.OpenAsync();

    var services = new ServiceCollection();
    services.AddLogging();
    services.AddDbContext<WidgetContext>(options =>
    {
        options.UseSqlite(conn);
    });
    var containerBuilder = new ContainerBuilder();
    containerBuilder.Populate(services);
    await using var serviceProvider = containerBuilder.Build();
    await using var db = serviceProvider.Resolve<WidgetContext>();
}

static async Task DoesNotWorkAsync()
{
    await using var conn = new SqliteConnection(new SqliteConnectionStringBuilder
    {
        DataSource = ":memory:",
    }.ConnectionString);
    await conn.OpenAsync();

    var services = new ServiceCollection();
    services.AddLogging();
    services.AddDbContext<WidgetContext>(options =>
    {
        options.UseSqlite(conn);
    });
    using var autoMock = AutoMock.GetLoose(containerBuilder =>
    {
        containerBuilder.Populate(services);
    });
    await using var db = autoMock.Create<WidgetContext>();
}

WidgetContext.cs

using Microsoft.EntityFrameworkCore;

namespace AutoMockTest;

internal sealed class WidgetContext : DbContext
{
    public DbSet<Widget> Widget { get; set; }

    public WidgetContext(DbContextOptions<WidgetContext> options) : base(options) { }
}

Widget.cs

namespace AutoMockTest;

internal sealed class Widget
{
    public long Id { get; set; }
}

AutoMockTest.csproj

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>net8.0</TargetFramework>
    <ImplicitUsings>enable</ImplicitUsings>
    <Nullable>enable</Nullable>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Autofac.Extensions.DependencyInjection" Version="10.0.0" />
    <PackageReference Include="Autofac.Extras.Moq" Version="6.1.1" />
    <PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="8.0.8" />
    <PackageReference Include="Microsoft.Extensions.Logging" Version="8.0.0" />
  </ItemGroup>

</Project>

Expected Behavior

No exceptions should be thrown.

Exception with Stack Trace

For some reason Exception.StackTrace only has the following short stacktrace:

System.NullReferenceException: 'Object reference not set to an instance of an object.'
   at Microsoft.Extensions.Logging.Logger.<IsEnabled>g__LoggerIsEnabled|15_0(LogLevel logLevel, ILogger logger, List`1& exceptions) in /_/src/libraries/Microsoft.Extensions.Logging/src/Logger.cs:line 101

Here is a more complete callstack:

>	Microsoft.Extensions.Logging.dll!Microsoft.Extensions.Logging.Logger.IsEnabled.__LoggerIsEnabled|15_0(Microsoft.Extensions.Logging.LogLevel logLevel, Microsoft.Extensions.Logging.ILogger logger, ref System.Collections.Generic.List<System.Exception> exceptions) Line 101	C#
 	Microsoft.Extensions.Logging.dll!Microsoft.Extensions.Logging.Logger.IsEnabled(Microsoft.Extensions.Logging.LogLevel logLevel) Line 84	C#
 	Microsoft.EntityFrameworkCore.dll!Microsoft.EntityFrameworkCore.Diagnostics.IDiagnosticsLogger.ShouldLog(Microsoft.EntityFrameworkCore.Diagnostics.EventDefinitionBase definition) Line 74	C#
 	Microsoft.EntityFrameworkCore.dll!Microsoft.EntityFrameworkCore.Diagnostics.CoreLoggerExtensions.RedundantAddServicesCallWarning(Microsoft.EntityFrameworkCore.Diagnostics.IDiagnosticsLogger<Microsoft.EntityFrameworkCore.DbLoggerCategory.Infrastructure> diagnostics, System.IServiceProvider serviceProvider) Line 1233	C#
 	Microsoft.EntityFrameworkCore.dll!Microsoft.EntityFrameworkCore.Internal.ServiceProviderCache.GetOrAdd.__BuildServiceProvider|4_1(Microsoft.EntityFrameworkCore.Infrastructure.IDbContextOptions _, (System.Collections.Concurrent.ConcurrentDictionary<Microsoft.EntityFrameworkCore.Infrastructure.IDbContextOptions, (System.IServiceProvider ServiceProvider, System.Collections.Generic.IDictionary<string, string> DebugInfo)>, Microsoft.EntityFrameworkCore.Infrastructure.IDbContextOptions) arguments) Line 163	C#
 	Microsoft.EntityFrameworkCore.dll!Microsoft.EntityFrameworkCore.Internal.ServiceProviderCache.GetOrAdd.AnonymousMethod__4_0(Microsoft.EntityFrameworkCore.Infrastructure.IDbContextOptions contextOptions, (System.Collections.Concurrent.ConcurrentDictionary<Microsoft.EntityFrameworkCore.Infrastructure.IDbContextOptions, (System.IServiceProvider ServiceProvider, System.Collections.Generic.IDictionary<string, string> DebugInfo)> _configurations, Microsoft.EntityFrameworkCore.Infrastructure.IDbContextOptions options) tuples) Line 70	C#
 	System.Collections.Concurrent.dll!System.Collections.Concurrent.ConcurrentDictionary<Microsoft.EntityFrameworkCore.Infrastructure.IDbContextOptions, (System.IServiceProvider, System.Collections.Generic.IDictionary<string, string>)>.GetOrAdd<(System.Collections.Concurrent.ConcurrentDictionary<Microsoft.EntityFrameworkCore.Infrastructure.IDbContextOptions, (System.IServiceProvider, System.Collections.Generic.IDictionary<string, string>)>, Microsoft.EntityFrameworkCore.Infrastructure.IDbContextOptions)>(Microsoft.EntityFrameworkCore.Infrastructure.IDbContextOptions key, System.Func<Microsoft.EntityFrameworkCore.Infrastructure.IDbContextOptions, (System.Collections.Concurrent.ConcurrentDictionary<Microsoft.EntityFrameworkCore.Infrastructure.IDbContextOptions, (System.IServiceProvider, System.Collections.Generic.IDictionary<string, string>)>, Microsoft.EntityFrameworkCore.Infrastructure.IDbContextOptions), (System.IServiceProvider, System.Collections.Generic.IDictionary<string, string>)> valueFactory, (System.Collections.Concurrent.ConcurrentDictionary<Microsoft.EntityFrameworkCore.Infrastructure.IDbContextOptions, (System.IServiceProvider, System.Collections.Generic.IDictionary<string, string>)>, Microsoft.EntityFrameworkCore.Infrastructure.IDbContextOptions) factoryArgument) Line 1222	C#
 	Microsoft.EntityFrameworkCore.dll!Microsoft.EntityFrameworkCore.Internal.ServiceProviderCache.GetOrAdd(Microsoft.EntityFrameworkCore.Infrastructure.IDbContextOptions options, bool providerRequired) Line 68	C#
 	Microsoft.EntityFrameworkCore.dll!Microsoft.EntityFrameworkCore.DbContext.DbContext(Microsoft.EntityFrameworkCore.DbContextOptions options) Line 128	C#
 	AutoMockTest.dll!AutoMockTest.WidgetContext.WidgetContext(Microsoft.EntityFrameworkCore.DbContextOptions<AutoMockTest.WidgetContext> options) Line 9	C#
 	[Lightweight Function]	
 	Autofac.dll!Autofac.Core.Activators.Reflection.BoundConstructor.Instantiate() Line 124	C#
 	Autofac.dll!Autofac.Core.Activators.Reflection.ReflectionActivator.UseSingleConstructorActivation.AnonymousMethod__0(Autofac.Core.Resolving.Pipeline.ResolveRequestContext context, System.Action<Autofac.Core.Resolving.Pipeline.ResolveRequestContext> next) Line 200	C#
 	Autofac.dll!Autofac.Core.Resolving.Middleware.DelegateMiddleware.Execute(Autofac.Core.Resolving.Pipeline.ResolveRequestContext context, System.Action<Autofac.Core.Resolving.Pipeline.ResolveRequestContext> next) Line 35	C#
 	Autofac.dll!Autofac.Core.Resolving.Pipeline.ResolvePipelineBuilder.BuildPipeline.AnonymousMethod__1(Autofac.Core.Resolving.Pipeline.ResolveRequestContext context) Line 276	C#
 	Autofac.dll!Autofac.Core.Resolving.Middleware.DisposalTrackingMiddleware.Execute(Autofac.Core.Resolving.Pipeline.ResolveRequestContext context, System.Action<Autofac.Core.Resolving.Pipeline.ResolveRequestContext> next) Line 29	C#
 	Autofac.dll!Autofac.Core.Resolving.Pipeline.ResolvePipelineBuilder.BuildPipeline.AnonymousMethod__1(Autofac.Core.Resolving.Pipeline.ResolveRequestContext context) Line 276	C#
 	Autofac.Extensions.DependencyInjection.dll!Autofac.Extensions.DependencyInjection.KeyedServiceMiddleware.Execute(Autofac.Core.Resolving.Pipeline.ResolveRequestContext context, System.Action<Autofac.Core.Resolving.Pipeline.ResolveRequestContext> next) Line 97	C#
 	Autofac.dll!Autofac.Core.Resolving.Pipeline.ResolvePipelineBuilder.BuildPipeline.AnonymousMethod__1(Autofac.Core.Resolving.Pipeline.ResolveRequestContext context) Line 276	C#
 	Autofac.dll!Autofac.Core.Resolving.Middleware.ActivatorErrorHandlingMiddleware.Execute(Autofac.Core.Resolving.Pipeline.ResolveRequestContext context, System.Action<Autofac.Core.Resolving.Pipeline.ResolveRequestContext> next) Line 33	C#
 	Autofac.dll!Autofac.Core.Resolving.Pipeline.ResolvePipelineBuilder.BuildPipeline.AnonymousMethod__1(Autofac.Core.Resolving.Pipeline.ResolveRequestContext context) Line 276	C#
 	Autofac.dll!Autofac.Core.Pipeline.ResolvePipeline.Invoke(Autofac.Core.Resolving.Pipeline.ResolveRequestContext context) Line 28	C#
 	Autofac.dll!Autofac.Core.Resolving.Middleware.RegistrationPipelineInvokeMiddleware.Execute(Autofac.Core.Resolving.Pipeline.ResolveRequestContext context, System.Action<Autofac.Core.Resolving.Pipeline.ResolveRequestContext> next) Line 28	C#
 	Autofac.dll!Autofac.Core.Resolving.Pipeline.ResolvePipelineBuilder.BuildPipeline.AnonymousMethod__1(Autofac.Core.Resolving.Pipeline.ResolveRequestContext context) Line 276	C#
 	Autofac.dll!Autofac.Core.Resolving.Middleware.SharingMiddleware.Execute.AnonymousMethod__0() Line 42	C#
 	Autofac.dll!Autofac.Core.Lifetime.LifetimeScope.CreateSharedInstance(System.Guid id, System.Func<object> creator) Line 366	C#
 	Autofac.dll!Autofac.Core.Lifetime.LifetimeScope.CreateSharedInstance(System.Guid primaryId, System.Guid? qualifyingId, System.Func<object> creator) Line 386	C#
 	Autofac.dll!Autofac.Core.Resolving.Middleware.SharingMiddleware.Execute(Autofac.Core.Resolving.Pipeline.ResolveRequestContext context, System.Action<Autofac.Core.Resolving.Pipeline.ResolveRequestContext> next) Line 40	C#
 	Autofac.dll!Autofac.Core.Resolving.Pipeline.ResolvePipelineBuilder.BuildPipeline.AnonymousMethod__1(Autofac.Core.Resolving.Pipeline.ResolveRequestContext context) Line 276	C#
 	Autofac.dll!Autofac.Core.Resolving.Pipeline.ResolvePipelineBuilder.BuildPipeline.AnonymousMethod__1(Autofac.Core.Resolving.Pipeline.ResolveRequestContext context) Line 276	C#
 	Autofac.dll!Autofac.Core.Resolving.Middleware.CircularDependencyDetectorMiddleware.Execute(Autofac.Core.Resolving.Pipeline.ResolveRequestContext context, System.Action<Autofac.Core.Resolving.Pipeline.ResolveRequestContext> next) Line 91	C#
 	Autofac.dll!Autofac.Core.Resolving.Pipeline.ResolvePipelineBuilder.BuildPipeline.AnonymousMethod__1(Autofac.Core.Resolving.Pipeline.ResolveRequestContext context) Line 276	C#
 	Autofac.dll!Autofac.Core.Pipeline.ResolvePipeline.Invoke(Autofac.Core.Resolving.Pipeline.ResolveRequestContext context) Line 28	C#
 	Autofac.dll!Autofac.Core.Resolving.ResolveOperation.InvokePipeline(Autofac.ResolveRequest request, Autofac.Core.Resolving.Pipeline.DefaultResolveRequestContext requestContext) Line 233	C#
 	Autofac.dll!Autofac.Core.Resolving.ResolveOperation.GetOrCreateInstance(Autofac.Core.ISharingLifetimeScope currentOperationScope, Autofac.ResolveRequest request) Line 132	C#
 	Autofac.dll!Autofac.Core.Resolving.ResolveOperation.ExecuteOperation(Autofac.ResolveRequest request) Line 180	C#
 	Autofac.dll!Autofac.Core.Resolving.ResolveOperation.Execute(Autofac.ResolveRequest request) Line 47	C#
 	Autofac.dll!Autofac.Core.Lifetime.LifetimeScope.ResolveComponent(Autofac.ResolveRequest request) Line 333	C#
 	Autofac.dll!Autofac.Core.Container.ResolveComponent(Autofac.ResolveRequest request) Line 145	C#
 	Autofac.dll!Autofac.Core.Container.Autofac.IComponentContext.ResolveComponent(Autofac.ResolveRequest request)	Unknown
 	Autofac.dll!Autofac.ResolutionExtensions.TryResolveService(Autofac.IComponentContext context, Autofac.Core.Service service, System.Collections.Generic.IEnumerable<Autofac.Core.Parameter> parameters, out object instance) Line 1107	C#
 	Autofac.dll!Autofac.ResolutionExtensions.ResolveService(Autofac.IComponentContext context, Autofac.Core.Service service, System.Collections.Generic.IEnumerable<Autofac.Core.Parameter> parameters) Line 870	C#
 	Autofac.dll!Autofac.ResolutionExtensions.Resolve(Autofac.IComponentContext context, System.Type serviceType, System.Collections.Generic.IEnumerable<Autofac.Core.Parameter> parameters) Line 336	C#
 	Autofac.dll!Autofac.ResolutionExtensions.Resolve(Autofac.IComponentContext context, System.Type serviceType, Autofac.Core.Parameter[] parameters) Line 352	C#
 	Autofac.Extras.Moq.dll!Autofac.Extras.Moq.AutoMock.Create(bool isMock, System.Type serviceType, Autofac.Core.Parameter[] parameters) Line 191	C#
 	Autofac.Extras.Moq.dll!Autofac.Extras.Moq.AutoMock.Create<AutoMockTest.WidgetContext>(bool isMock, Autofac.Core.Parameter[] parameters) Line 196	C#
 	Autofac.Extras.Moq.dll!Autofac.Extras.Moq.AutoMock.Create<AutoMockTest.WidgetContext>(Autofac.Core.Parameter[] parameters) Line 144	C#
 	AutoMockTest.dll!Program.<Main>$.__DoesNotWorkAsync|0_1() Line 50	C#
 	AutoMockTest.dll!Program.<Main>$(string[] args) Line 9	C#
 	AutoMockTest.dll!Program.<Main>(string[] args)	Unknown

Dependency Versions

Autofac: 8.1.0
Autofac.Extras.Moq: 6.1.1
Autofac.Extensions.DependencyInjection: 10.0.0
Microsoft.EntityFrameworkCore.Sqlite: 8.0.8
Microsoft.Extensions.Logging: 8.0.0

Additional Info

The fact that things work when not using AutoMock suggests to me that the problem is in AutoMock somehow. It's also completely possible that I'm doing something wrong.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions