pengweiqhca / Xunit.DependencyInjection

Use Microsoft.Extensions.DependencyInjection to resolve xUnit test cases.
MIT License
370 stars 49 forks source link

Support for property injection #120

Closed michaeltg17 closed 6 months ago

michaeltg17 commented 6 months ago

Usually you have dependencies in the constructor of each test class like this:

public class MyTestClass(IDependency dependency, ITestOutputHelper testOutputHelper) : MyTestBase(dependency, testOutputHelper)
{
   [Fact]
   public void SomeTest()
   {
   }
}

But sometimes you only use them in the base class so the ideal code would look like this:

public class MyTestClass : MyTestBase
{
   [Fact]
   public void SomeTest()
   {
   }
}

To achive this, having support for property injection would be nice.

In this project you can have it: https://github.com/flavien/quickwire

The problem is that the test class is created outside the DI container and its dependencies passed manually (only constructor's ones).

I think it won't be hard to add support for property injection as the main work is already done.

pengweiqhca commented 6 months ago

Supported at 9.2.1

See demo

michaeltg17 commented 6 months ago

Hi.

I tried it but it only works with services registered in the Startup class or with the ITestOutputHelperAccessor.

I have an scenario in which I need something like this:

public class BeforeAfterTestConfiguration(WebApplicationFactoryFixture webApplicationFactoryFixture, ITestOutputHelper testOutputHelper)
    : BeforeAfterTest
{
    public override void Before(object? testClassInstance, MethodInfo methodUnderTest)
    {
        if (testClassInstance is Test test)
        {
            test.WebApplicationFactoryFixture = webApplicationFactoryFixture;
            test.TestOutputHelper = testOutputHelper.Output;
            test.Initialize();
        }
    }
}

These parameters (collection fixture and test output) are injected fine in the current running test class but not in this BeforeAfterTest class.

pengweiqhca commented 6 months ago
  1. TestFixture is xunit feature, you must register it as a (keyed) service.

  2. ITestOutputHelper => ITestOutputHelperAccessor

michaeltg17 commented 6 months ago

How would you register it? Okay keyed but what lifetime and what key? I'm not able to see how it would work.

In my case the fixture has an IMessageSink parameter as well.

WebApplicationFactoryFixture(IMessageSink messageSink)

Okay with point 2.

pengweiqhca commented 6 months ago

services.AddScoped<WebApplicationFactoryFixture>(), public class BeforeAfterTestConfiguration(WebApplicationFactoryFixture webApplicationFactoryFixture) or services.AddKeyedSingleton<WebApplicationFactoryFixture>(KeyedService.AnyKey), public class BeforeAfterTestConfiguration([FromKeyedServices("someKey")]WebApplicationFactoryFixture webApplicationFactoryFixture)

michaeltg17 commented 6 months ago

Okay, it works perfectly. Thanks!