Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Exception throw in dotnet8 (working in dotnet6) #1454

Closed
p1971 opened this issue Jan 4, 2024 · 2 comments
Closed

Exception throw in dotnet8 (working in dotnet6) #1454

p1971 opened this issue Jan 4, 2024 · 2 comments
Labels

Comments

@p1971
Copy link

p1971 commented Jan 4, 2024

Describe the Bug

I have a test that asserts that an extension method correctly registers all required dependencies such that clients should have everything fully registered. On dotnet8 this throws an exception. I've included a cut-down example.

Steps to Reproduce

Execute the code below - net6 works - net8 fails

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

  <PropertyGroup>
    <TargetFrameworks>net6.0;net8.0</TargetFrameworks>
    <ImplicitUsings>enable</ImplicitUsings>
    <Nullable>enable</Nullable>
    <LangVersion>latest</LangVersion>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="8.0.0" />
    <PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="8.0.0" />
    <PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.8.0" />
    <PackageReference Include="Moq" Version="4.20.70" />
    <PackageReference Include="xunit" Version="2.6.4" />
    <PackageReference Include="xunit.runner.visualstudio" Version="2.5.6">
      <PrivateAssets>all</PrivateAssets>
      <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
    </PackageReference>
  </ItemGroup>

</Project>
public class ExampleOfFailingTest
{
    [Fact]
    public void ServiceProviderShouldResolveTheInterface()
    {    
        IServiceCollection subject = new ServiceCollection();

        // Create a mocked interface
        Mock<ITestInterface<TestClass>> mockInterface = new();

        // add it to the service collection
        subject.TryAddSingleton(typeof(ITestInterface<TestClass>), mockInterface.Object.GetType());

        // build the service provider
        ServiceProvider serviceProvider = subject.BuildServiceProvider();

        // now get an instance of the service
        Assert.NotNull(serviceProvider.GetService<ITestInterface<TestClass>>());
    }
}

public class TestClass
{
}

public interface ITestInterface<in T>
    where T : class
{
    Task DoSomeWork(T request);
}

Expected Behavior

Should also pass on dotnet8

Exception with Stack Trace

System.InvalidOperationException
Unable to resolve service for type 'Castle.DynamicProxy.IInterceptor[]' while attempting to activate 'Castle.Proxies.ITestInterface`1Proxy'.
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.CreateArgumentCallSites(ServiceIdentifier serviceIdentifier, Type implementationType, CallSiteChain callSiteChain, ParameterInfo[] parameters, Boolean throwIfCallSiteNotFound)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.CreateConstructorCallSite(ResultCache lifetime, ServiceIdentifier serviceIdentifier, Type implementationType, CallSiteChain callSiteChain)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.TryCreateExact(ServiceDescriptor descriptor, ServiceIdentifier serviceIdentifier, CallSiteChain callSiteChain, Int32 slot)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.TryCreateExact(ServiceIdentifier serviceIdentifier, CallSiteChain callSiteChain)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.CreateCallSite(ServiceIdentifier serviceIdentifier, CallSiteChain callSiteChain)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.GetCallSite(ServiceIdentifier serviceIdentifier, CallSiteChain callSiteChain)
   at Microsoft.Extensions.DependencyInjection.ServiceProvider.CreateServiceAccessor(ServiceIdentifier serviceIdentifier)
   at System.Collections.Concurrent.ConcurrentDictionary`2.GetOrAdd(TKey key, Func`2 valueFactory)
   at Microsoft.Extensions.DependencyInjection.ServiceProvider.GetService(ServiceIdentifier serviceIdentifier, ServiceProviderEngineScope serviceProviderEngineScope)
   at Microsoft.Extensions.DependencyInjection.ServiceProvider.GetService(Type serviceType)
   at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetService[T](IServiceProvider provider)
   at MoqTest.ExampleOfFailingTest.ServiceProviderShouldResolveTheInterface() in E:\temp\src\moq\MoqTest\MoqTest\Class1.cs:line 26
   at System.RuntimeMethodHandle.InvokeMethod(Object target, Void** arguments, Signature sig, Boolean isConstructor)
   at System.Reflection.MethodBaseInvoker.InvokeWithNoArgs(Object obj, BindingFlags invokeAttr)

Version Info

Moq - 4.20.70

@p1971 p1971 added the bug label Jan 4, 2024
@snowinmars
Copy link

See dotnet/runtime#102888

@kzu
Copy link
Member

kzu commented Jun 15, 2024

If you want the service collection to return your previously constructed mock from its GetService, you need to register the function to retrieve it, not the mock type which the container doesn't know how to instantiate:

subject.TryAddSingleton(typeof(ITestInterface<TestClass>), sp => mockInterface.Object);

@kzu kzu closed this as not planned Won't fix, can't repro, duplicate, stale Jun 15, 2024
@kzu kzu added invalid and removed bug labels Jun 15, 2024
@devlooped devlooped locked and limited conversation to collaborators Sep 4, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

No branches or pull requests

3 participants