How to use AutoFixture to customize a collection

Viewed 24

I would like to start using AutoFixture, but I do have a question how to customize a collection.

Given the following class:

public sealed class Contract
{
    public DateTime StartDate { get; set; }
}

I would like to use AutoFixture's ISpecimenBuilder (or anything else), to create a collection of Contracts.

I would like to pass to my specimen a Date/Time and as a result, when I'm asking AutoFixture for a collection of Contract instances, I would like to have returned 3:

  • 1 with a Start Date, in the past (based on the Date/Time I have provided to the ISpecimen).

  • 1 with a Start Date, matching the current date (based on the Date/Time I have provided to the ISpecimen).

  • 1 with a Start Date, in the future (based on the Date/Time I have provided to the ISpecimen).

After reading and playing with it, I believe I need something like a Seed, but I don't get anything working, any advice on how to tackle this?

1 Answers

Using this answer, I tried to use the post-processing feature. I think this is close.

Create command to set the StartDate. The only way I could find of passing the 'seed' date was via the constructor. The only bit left to solve here is how to know where you are in the collection and set the date accordingly.

public class SeedStartDateCommand : ISpecimenCommand
{
   private DateTime _seedDate;

   public SeedStartDateCommand(DateTime seedDate)
   {
      _seedDate = seedDate;
   }

   public void Execute(object specimen, ISpecimenContext context)
   {
      if (specimen is not Contract contract)
      {
         return;
      }

      // This is where you need to work out where you are in the 
      // collection. I.e. is this 0, -1 or +1?
      contract.StartDate = _seedDate;
   }
}

Then wire this up with the fixture. It's quite verbose, so could be hidden in an extension method. Also, I took that code from the other answer, so it could be that all that PostProcessor wiring isn't essential.

var fixture = new Fixture();

var seedDate = DateTime.UtcNow;

fixture.Customizations.Add(
   SpecimenBuilderNodeFactory.CreateTypedNode(
       typeof(Contract),
       new Postprocessor(
          new MethodInvoker(
             new ModestConstructorQuery()),
             new CompositeSpecimenCommand(
                new AutoPropertiesCommand(),
                new SeedStartDateCommand(seedDate)))));

var contracts = fixture.CreateMany<Contract>();

I don't think this is the final solution, but it seems to get close...

Related