nunit / nunit-console

NUnit Console runner and test engine
MIT License
215 stars 152 forks source link

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

Open Sputnik24 opened 1 year ago

Sputnik24 commented 1 year ago

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 commented 1 year ago

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 commented 1 year ago

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:

Behavior:

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.

CharliePoole commented 1 month ago

@Sputnik24 Can you try this using the latest build of NUnit.ConsoleRunner from our myget feed? You may also want to try NUnit.ConsoleRunner.Net80.

Sputnik24 commented 1 month ago

@CharliePoole Retestet wit NUnit Console Runner 3.18.3-dev00009. Issue still occurs:

NUnit Console Runner 3.18.3-dev00009 (Release)
Copyright (c) 2022 Charlie Poole, Rob Prouse
Samstag, 5. Oktober 2024 08:00:45

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

Test Files
    D:\dev\repos\AutofacNUnit\AutofacNUnitTest\bin\Debug\net8.0\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 D:\dev\repos\AutofacNUnit\AutofacNUnitTest\ServiceFactory.cs:line 28
   at AutofacNUnitTest.ServiceFactoryTests.FakeServiceDiffProjects() in D:\dev\repos\AutofacNUnit\AutofacNUnitTest\ServiceFactoryTests.cs:line 18
   at System.RuntimeMethodHandle.InvokeMethod(Object target, Void** arguments, Signature sig, Boolean isConstructor)
   at System.Reflection.MethodBaseInvoker.InvokeWithNoArgs(Object obj, BindingFlags invokeAttr)

Run Settings
    DisposeRunners: True
    WorkDirectory: C:\Downloads\NUnit.ConsoleRunner.3.18.3-dev00009\tools
    ImageRuntimeVersion: 4.0.30319
    ImageTargetFrameworkName: .NETCoreApp,Version=v8.0
    ImageRequiresX86: False
    ImageRequiresDefaultAppDomainAssemblyResolver: False
    TargetRuntimeFramework: netcore-8.0
    NumberOfTestWorkers: 16

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: 2024-10-05 06:00:46Z
    End time: 2024-10-05 06:00:47Z
    Duration: 1.005 seconds

Results (nunit3) saved as TestResult.xml
CharliePoole commented 1 month ago

A workaround may be to use NUnit.ConsoleRunner.Net80, same version.

Sputnik24 commented 1 month ago

Same error

CharliePoole commented 1 month ago

OK, I'll move ahead with the release and come back to this issue in the 3.19 series.