How can I modify the fixture my custom theory data attribute creates for AutoFixture?

StackOverflow https://stackoverflow.com/questions/13128446

  •  15-07-2021
  •  | 
  •  

I'm really appreciating the power of AutoFixture coupled with XUnit's theories. I've recently adopted the use of encapsulating customizations and providing them to my tests via an attribute.

On certain occasions, I need a one-off scenario to run my test with. When I use an AutoDomainDataAttribute, like above, can I ask for an IFixture and expect to get the same instance created by the attribute?

In my scenario, I'm using MultipleCustomization by default for collections, etc. However, in this one case, I want only a single item sent to my SUT's constructor. So, I've defined my test method like so:

[Theory, AutoDomainData]
public void SomeTest(IFixture fixture) {
  fixture.RepeatCount = 1;
  var sut = fixture.CreateAnonymous<Product>();
  ...
}

Unfortunately, I'm getting an exception when creating the anonymous Product. Other tests work just fine, if I ask for a Product as a method parameter with those attributes. It's only an issue in this particular case, where I'm hoping that the fixture parameter is the same one created by my AutoDomainDataAttribute.

Product's constructor expects an IEnumerable that normally gets populate with 3 items, due to the customizations I have in-place via AutoDomainData. Currently, my DomainCustomization is a CompositeCustomization made up of MultipleCustomization and AutMoqCustomization, in that order.

The exception is: "InvalidCastException: Unable to cast object of type 'Castle.Proxies.ObjectProxy' to type 'Product'."

有帮助吗?

解决方案

If you need the same Fixture instance as the one active in the attribute, you can inject the Fixture into itself in a Customization, like this:

public class InjectFixtureIntoItself : ICustomization
{
    public void Customize(IFixture fixture)
    {
        fixture.Inject(fixture);
    }
}

Just remember to add this to your CompositeCustomization before AutoMoqCustomization, since IFixture is an interface, and if AutoMoqCustomization comes first, you'll get a Mock instance instead - AFAICT, that's what's currently happening with the dynamic Castle proxy.


However, if you really need a Fixture instance, why not just write a regular, imperative test method:

[Fact]
public void SomeTest()
{
    var fixture = new Fixture().Customize(new DomainCustomization());
    fixture.RepeatCount = 1;
    var sut = fixture.CreateAnonymous<Product>();
    // ...
}

That seems to me to be much easier... I occasionally do this myself too...


Still, I wonder if you couldn't phrase your API or test case in a different way to make the whole issue go away. I very rarely find that I have to manipulate the RepeatCount property these days, so I wonder why you would want to do that?

That's probably the subject of a separate Stack Overflow question, though...

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top