5

I have xUnit/Moq/AutoFixture successfully working together so that I am auto mocking objects via test method input parameters. I created a custom [AutoMoqData] attribute which I use on every test. Here's the code for the attribute:

using System.Linq;
using AutoFixture;
using AutoFixture.AutoMoq;
using AutoFixture.Xunit2;

namespace Shared.TestResources.AutoFixture
{
    public class AutoMoqDataAttribute : AutoDataAttribute
    {
        public AutoMoqDataAttribute() : base(() => new Fixture().Customize(new CompositeCustomization(new AutoMoqCustomization(), new SupportMutableValueTypesCustomization())))
        {
            this.Fixture.Behaviors.OfType<ThrowingRecursionBehavior>().ToList().ForEach(b => Fixture.Behaviors.Remove(b));
            this.Fixture.Behaviors.Add(new OmitOnRecursionBehavior());
        }
    }
}

This works, but I get the following compile warning: warning CS0618: 'AutoDataAttribute.Fixture' is obsolete: 'Fixture is created lazily for the performance efficiency, so this property is deprecated as it activates the fixture immediately. If you need to customize the fixture, do that in the factory method passed to the constructor.'

I've muted the warning by surrounding it with a #pragma:

using System.Linq;
using AutoFixture;
using AutoFixture.AutoMoq;
using AutoFixture.Xunit2;

namespace Shared.TestResources.AutoFixture
{
    public class AutoMoqDataAttribute : AutoDataAttribute
    {
        public AutoMoqDataAttribute() : base(() => new Fixture().Customize(new CompositeCustomization(new AutoMoqCustomization(), new SupportMutableValueTypesCustomization())))
        {
#pragma warning disable 0618
            this.Fixture.Behaviors.OfType<ThrowingRecursionBehavior>().ToList().ForEach(b => Fixture.Behaviors.Remove(b));
            this.Fixture.Behaviors.Add(new OmitOnRecursionBehavior());
#pragma warning restore 0618
        }
    }
}

However, I want to set this up correctly and not have to pretend like the warning doesn't exist. The problem is, I'm having trouble figuring out the correct syntax for the two lines inside of the #pragma.

Any ideas?

Andr
  • 1,043
  • 4
  • 13
  • 15
  • We worked with xUnit/NSubstitute/AutoFixture in a similar setup. Our conclusion is that you should not use AutoFixture as this is not compatible with ncrunch (or anything else that relies on static analysis to pick up tests that needs to run; i.e. anything that runs your unit tests fast) and results in false negatives much more frequent than discovering uncovered special cases; i.e. CI fails for reasons that has nothing to do with recent changes. – Robert Jørgensgaard Engdahl Jan 18 '19 at 20:57
  • @RobertJørgensgaardEngdahl In fact, AutoFixture __is fully compatible__ with NCrunch, as [it has been confirmed](https://github.com/AutoFixture/AutoFixture/issues/805) by the tool developer. It's especially true for xUnit, which provides native support for the theories with dynamic data (which AutoFixture relies on). If you observe any issues - please report them either to AutoFixture or to NCrunch - depending on their origin. – Alex Povar Jan 26 '19 at 20:39
  • I admit there are ways to use NCrunch and AutoFixture together (and the problem is not NCrunch which is an amazing tool with great support). I also admit that the false negatives can be avoided (by careful design). But for the same reasons as I gave above, I still don't recommend using AutoFixture. – Robert Jørgensgaard Engdahl Jan 28 '19 at 08:59
  • It is b.t.w. not fully compatible. In your own link Remco explains exactly when it won't work :) – Robert Jørgensgaard Engdahl Jan 28 '19 at 08:59
  • I'm afraid we are just speculating around the topic without the concrete facts. To my knowledge and experience AutoFixture is fully compatible with NCrunch without __any issues__. If you know that issues exist - please report them, so we can investigate and troubleshoot them together. Remco confirmed that as well (if you read and follow carefully the whole thread). I just want to omit situations when false rumors are spread around. Both tools are nice and people will only benefit from using them both. – Alex Povar Jan 30 '19 at 19:21
  • These issues are reported to NCrunch in their support forum months ago (https://forum.ncrunch.net/yaf_postst2157_Framework-Utilisation-Types-missing-Xunit-v2.aspx). There is no issue with NCrunch, the issues are with AutoFixture; and the issues are not with how AutoFixture is implemented, but rather what it is used for. When do you spend time fixing flaky tests that are discovered in tests written a year ago @AlexPovar? – Robert Jørgensgaard Engdahl Jan 31 '19 at 08:59

1 Answers1

6

Just use a lambda with body to additionally configure the fixture instance before returning it:

public class AutoMoqDataAttribute : AutoDataAttribute
{
    public AutoMoqDataAttribute() : base(() =>
    {
        var fixture = new Fixture().Customize(new CompositeCustomization(
            new AutoMoqCustomization(),
            new SupportMutableValueTypesCustomization()));

        fixture.Behaviors.OfType<ThrowingRecursionBehavior>().ToList().ForEach(b => Fixture.Behaviors.Remove(b));
        fixture.Behaviors.Add(new OmitOnRecursionBehavior());

        return fixture;
    })
    {
    }
}

This way the Fixture activation will be truly lazy and you will get the expected performance optimization ;-)

Alex Povar
  • 674
  • 3
  • 15