4

Here is what I am trying to do:

public class MyTests
{
    private IFixture _fixture;

    public MyTests()
    {
        _fixture = new Fixture();
        _fixture.Customize<Thing>(x => x.With(y => y.UserId, 1));
    }

    [Theory, AutoData]
    public void GetThingsByUserId_ShouldReturnThings(IEnumerable<Thing> things)
    {
        things.First().UserId.Should().Be(1);
    }
}

I would expect the IEnumerable<Thing> things parameter passed into the test to each have a UserId of 1 but this is not what happens.

How can I make this so?

Holf
  • 5,605
  • 3
  • 42
  • 63

1 Answers1

5

You can do that by creating a custom AutoData attribute derived-type:

internal class MyAutoDataAttribute : AutoDataAttribute
{
    internal MyAutoDataAttribute()
        : base(
            new Fixture().Customize(
                new CompositeCustomization(
                    new MyCustomization())))
    {
    }

    private class MyCustomization : ICustomization
    {
        public void Customize(IFixture fixture)
        {
            fixture.Customize<Thing>(x => x.With(y => y.UserId, 1));
        }
    }
}

You may also add other Customizations. Just keep in mind that the order matters.


Then, change the test method to use MyAutoData attribute instead, as shown below:

public class MyTests
{
    [Theory, MyAutoData]
    public void GetThingsByUserId_ShouldReturnThings(IEnumerable<Thing> things)
    {
        things.First().UserId.Should().Be(1);
    }
}
Nikos Baxevanis
  • 10,868
  • 2
  • 46
  • 80
  • 2
    Could there be a solution, which enables the form Holf posted? I feel like doing the customization in the ctor has less ceremony, than creating an attribute and customization classes. In simple, non-reusable cases it would be nice to have that option too. – ike Jan 30 '20 at 10:27
  • The *form Holf posted*? What does that mean? – Nikos Baxevanis Jan 31 '20 at 11:02
  • Sorry, what I mean is the usage pattern assumed in OPs question, where one could instantiate and customize a fixture in the constructor of a test class, while still being able to use AutoData on a test method, which would use the same fixture used in the constructor. – ike Feb 01 '20 at 12:40
  • I had to define the constructor of `MyAutoDataAttribute` public for this to work. Also, replace with function in call to `AutoDataAttribute` constructor like so: `base(() => new Fixture().Customize(new CompositeCustomization(new MyCustomization())))` – MikkelRJ Mar 09 '21 at 08:13