Is is possible to have ITestOutputHelper created by xUnit to be available in AutoFixture context?
Asked Answered
R

2

11

Is is possible to have ITestOutputHelper created by xUnit to be available in AutoFixture context?

In my integration tests I use Builder class that contains helper methods for some routine operations. In order to hide complexity of class creation I use custom AutoDataAttribute, so my tests are getting created object as test method parameter from AutoFixture.

Now I decided to add some logging functionality to Builder and can't find out how to pass ITestOutputHelper into Builder constructor from custom AutoDataAttribute.

using Ploeh.AutoFixture;
using Ploeh.AutoFixture.AutoNSubstitute;
using Ploeh.AutoFixture.Xunit2;
using Xunit;
using Xunit.Abstractions;

namespace XunitAutoFixtItestOutput
{
    public class Class1Tests
    {
        private readonly ITestOutputHelper _output;

        public Class1Tests(ITestOutputHelper output)
        {
            _output = output;
        }

        [Theory, DefaultAutoData]
        public void UnitOfWork_StateUnderTest_ExpectedBehavior(Builder builder)
        {
        }
    }

    public class Builder
    {
        private readonly ITestOutputHelper _outputHelper;

        public Builder(ITestOutputHelper outputHelper)
        {
            _outputHelper = outputHelper;
        }

        public void DoSomething()
        {
            _outputHelper.WriteLine("Something happened");
        }
    }

    public class DefaultAutoData : AutoDataAttribute
    {
        public DefaultAutoData() : base(new Fixture().Customize(new DefaultCustomization()))
        {
            this.Fixture.Customize<Builder>(f => f.FromFactory(new Builder(??Where to get it from??)));
        }
    }

    public class DefaultCustomization : CompositeCustomization
    {
        public DefaultCustomization() : base(new AutoConfiguredNSubstituteCustomization())
        {
        }
    }
}
Refrigerator answered 11/2, 2017 at 21:38 Comment(3)
xUnit.net controls the lifetime of the test classes, as well as it creates the ITestOutputHelper instance that gets passed to the test class' constructor. I don't have the full view of what xUnit.net's API enables you to do, but unless it provides an extensibility point that enables you to get the injected ITestOutputHelper when DataAttribute.GetData is invoked, I don't think this is possible...Yacketyyak
Thank you for information, will have a look at DataAttribute.Refrigerator
@MichaelBaranov have you managed to find any solution to it?Create
D
3

As Mark Seemann foresaw in the comments, it's not supported in the current version (v2.1) and there is no visible extensibility point. Therefore, it might be added in future versions.

There is a suggestion to sacrifice the AutoData attribute (at least until xUnit is extended) and configure fixture in the test constructor:

public class Class1Tests
{
  private readonly Fixture fixture;

  public Class1Tests(ITestOutputHelper output)
  {
    this.fixture = new Fixture();
    this.fixture.Inject(output);
  }

  [Fact]
  public void UnitOfWork_StateUnderTest_ExpectedBehavior()
  {
    var builder = this.fixture.Create<Builder>();
    builder.DoSomething();
  }
}
Dummy answered 14/2, 2017 at 19:29 Comment(2)
Just for reference, fixture.Freeze() is the exact same as fixture.Inject(fixture.Create(...)). https://mcmap.net/q/294259/-can-39-t-grasp-the-difference-between-freeze-inject-registerDale
Wouldn't this mean test per file ?Totally
S
2

You can add the xUnit.DependencyInjection NuGet package to your project, and then take the ITestOutputHelperAccessor into your Fixture constructor. It has just one property, Output. That is the ITestOutputHelper for the current test. However, it's of limited use because your fixture is called before and after the tests have been run. So there is no test output while your fixture code is executing.

Seymore answered 27/7, 2022 at 15:54 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.