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

DependencyInjection via Autofac not working properly using NUnit console (or testcentric GUI) #1353

Open
Sputnik24 opened this issue Jul 27, 2023 · 2 comments

Comments

@Sputnik24
Copy link

Sputnik24 commented Jul 27, 2023

In my NUnit-Test I register some services using Autofac library:

[Test]
public void Test() {
    var builder = new ContainerBuilder();
    builder.RegisterType(typeof(FakeServiceNoConfig)).AsSelf().As<IStartable>().SingleInstance();
    IContainer container = builder.Build();

    Assert.IsTrue(container.TryResolve(out IFakeServiceNoConfig? service));
    container.Dispose();
}
public class FakeServiceNoConfig : IFakeServiceNoConfig, IStartable, IDisposable {
    public void Start() { }

    public void Dispose() { }
}

public interface IFakeServiceNoConfig { }

When I run the test using testcentric GUI or nunit3-console.exe or dotnet nunit3-netcore-console.dll I receive the following exception

System.ArgumentException : The type 'UnitTests.ServiceFactoryTest.FakeServiceNoConfig' is not assignable to service 'Autofac.IStartable'.

When I remove the IStarble form the builder, I get:

1) Failed : UnitTests.ServiceFactoryTests.ServiceWithoutConfig
  Expected: True
  But was:  False

When I run the same using dotnet test, the test passes.

Is this an issue with NUnit Console/GUI or do I do something wrong?

Thanks a lot
Daniel

@stevenaw
Copy link
Member

stevenaw commented Jul 27, 2023

Thanks for reporting this @Sputnik24

To help us out, are you able to share a csproj example that would show can the package versions and runtime for your example?

EDIT: Another option for sharing this info could be to put up a PR for your repro in our https://github.com/nunit/nunit-console.issues repo

@Sputnik24
Copy link
Author

Thanks for your comment @stevenaw

I further investigated the issue and uploaded a simplified solution which reproduced the issue: https://github.com/Sputnik24/AutofacNUnit

Details:

  • There is a ServiceFactory in each class project. The implementation of the ServiceFactories is the same.
  • The difference is that AutofacNUnitLib.ServiceFactory is in the same project as the FakeService, where AutofacNUnitTest.ServiceFactory is in a different project than the FakeService.
  • I implemented two tests: FakeServiceSameProject, which uses AutofacNUnitLib.ServiceFactory and FakeServiceDiffProject which uses the other.
  • To get additional information, the ServiceFactory in AutofacNUnitTest prints the FullName of the type to register and its iterfaces to the NUnit console.

Behavior:

  • Running the test in my IDE (Rider): Both tests succeed
  • Running the test using dotnet test: Both tests succed
  • Running the test using either nunit3-console.exe or dotnet nunit3-netcore-console.dll: FakeServiceSameProject succeeds but FakeServiceDiffProject fails with:
C:\dev\nunit\nunit3-console.exe .\AutofacNUnitTest.dll
NUnit Console 3.16.2 (Release)
Copyright (c) 2022 Charlie Poole, Rob Prouse
Freitag, 28. Juli 2023 08:34:25

Runtime Environment
   OS Version: Microsoft Windows NT 6.2.9200.0
   Runtime: .NET Framework CLR v4.0.30319.42000

Test Files
    .\AutofacNUnitTest.dll

AutofacNUnitLib.FakeService:
AutofacNUnitLib.IFakeService
Autofac.IStartable
System.IDisposable

Errors, Failures and Warnings

1) Error : AutofacNUnitTest.ServiceFactoryTests.FakeServiceDiffProjects
System.ArgumentException : The type 'AutofacNUnitLib.FakeService' is not assignable to service 'Autofac.IStartable'.
   at Autofac.Builder.RegistrationBuilder.CreateRegistration(Guid id, RegistrationData data, IInstanceActivator activator, IResolvePipelineBuilder pipelineBuilder, Service[] services, IComponentRegistration target)
   at Autofac.Builder.RegistrationBuilder.CreateRegistration[TLimit,TActivatorData,TSingleRegistrationStyle](IRegistrationBuilder`3 builder)
   at Autofac.Builder.RegistrationBuilder.RegisterSingleComponent[TLimit,TActivatorData,TSingleRegistrationStyle](IComponentRegistryBuilder cr, IRegistrationBuilder`3 builder)
   at Autofac.RegistrationExtensions.<>c__DisplayClass40_0.<RegisterType>b__0(IComponentRegistryBuilder cr)
   at Autofac.ContainerBuilder.Build(IComponentRegistryBuilder componentRegistry, Boolean excludeDefaultModules)
   at Autofac.ContainerBuilder.Build(ContainerBuildOptions options)
   at AutofacNUnitTest.ServiceFactory.CreateContainer(String typeName, String interfaceName) in C:\dev\repos\AutofacNUnit\AutofacNUnitTest\ServiceFactory.cs:line 28
   at AutofacNUnitTest.ServiceFactoryTests.FakeServiceDiffProjects() in C:\dev\repos\AutofacNUnit\AutofacNUnitTest\ServiceFactoryTests.cs:line 18
   at System.RuntimeMethodHandle.InvokeMethod(Object target, Void** arguments, Signature sig, Boolean isConstructor)
   at System.Reflection.MethodInvoker.Invoke(Object obj, IntPtr* args, BindingFlags invokeAttr)

Run Settings
    DisposeRunners: True
    WorkDirectory: C:\dev\repos\AutofacNUnit\AutofacNUnitTest\bin\Debug\net7.0
    ImageRuntimeVersion: 4.0.30319
    ImageTargetFrameworkName: .NETCoreApp,Version=v7.0
    ImageRequiresX86: False
    ImageRequiresDefaultAppDomainAssemblyResolver: False
    TargetRuntimeFramework: netcore-7.0
    NumberOfTestWorkers: 8

Test Run Summary
  Overall result: Failed
  Test Count: 2, Passed: 1, Failed: 1, Warnings: 0, Inconclusive: 0, Skipped: 0
    Failed Tests - Failures: 0, Errors: 1, Invalid: 0
  Start time: 2023-07-28 06:34:26Z
    End time: 2023-07-28 06:34:28Z
    Duration: 2.661 seconds

Details on ServiceFactory:
The intention is to register type and interface given by its fullname as string (read from a config). Owing to lazy loading of assemblies the assembly containing this type/interface may not be loaded and is not found by Type.GetType(). Therefore, I implemented the FindAssemblyInBin loading all dlls from the executing folder. This works. With my debugger I see that foundType and foundInterface are correct and implement the correct interfaces (if they are null, RegisterType() would fail anyway). In the printout of the foundType you also see that the type is correct and that Autofac.IStartable is implemented.

Removing As or reducing it even to builder.Registertype(foundType).SingleInstance() doesn't work, either. In this case, the Assert.IsTrue fails as it cannot resolve the type, though it is registered.

@Sputnik24 Sputnik24 reopened this Jul 28, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants