6

(I didn't find a way to do this, from source code it appears it is not supported, but I might have overlooked it)

I would like to do something akin to:

(new Fixture())
    .CreateAnonymous<Circle>(
        new CircleSpecification { MinRadius = 1, MaxRadius = 5 }
    );

So this is a variation on a similar seed-idiom present in AutoFixture already, but seed idiom is very hard coded (or so I think).

Quiestion: Is it possible to customize a fixture to accept an argument for a specimen?

The best idea I have so far is to build a special Specification class that includes the result object, so that you can do:

public class CircleSpecification {
    public double MinRadius { get; set; }
    public double MaxRadius { get; set; }

    public Circle Circle { get; set; }
}

so that I can register CircleSpecificationSpecimenBuilder that can be used:

Circle circle = Fixture.CreateAnonymous<CircleSpecification>(
    new CircleSpecification { MinRadius = 0.0, MaxRadius = 5.0 }).Circle;

notice that to use CreateAnonymous with seed overload seed argument type has to match method return type.

THX-1138
  • 21,316
  • 26
  • 96
  • 160
  • What are you trying to accomplish with this? – Mark Seemann Jan 29 '13 at 18:22
  • 2
    I want to create a library of test data builders I can use to write unit tests (or integration tests). So that I can build a business object as in: `var bill = Fixture.CreateAnonymous(new BillSpec { TotalAmount = 120.00, Tip = 15.00 });` - and get a bill with many items in it. I can just build a helper method, but it feels like if I am using AutoFixture, I should have AutoFixture to build objects, if I build my Bill outside of AutoFixture, why do I need AutoFixture ? – THX-1138 Jan 29 '13 at 20:01
  • How does the `Bill` (or `Circle`) class look? – Mark Seemann Jan 29 '13 at 20:34
  • `public class Circle { public double Radius { get; set; } }` – THX-1138 Jan 29 '13 at 20:37
  • So, are you attempting to constrain the range of the Radius property to between 0 and 5? How does that relate to the `Bill` example? Is it important that these properties have those specific values? I'm finding it a bit difficult to see a pattern :$ – Mark Seemann Jan 29 '13 at 21:48
  • While we are zeroing in on the core question, this related discussion may be helpful: http://stackoverflow.com/questions/10125199/autofixture-configure-fixture-to-limit-string-generation-length – Mark Seemann Jan 29 '13 at 21:50
  • 1
    For my testing, sometimes I want Circle with radius 0, sometimes I want it to be very large, and sometimes I want bunch of circles with radius anywhere between 0 and 5. So I am inquiring if AF API allows to provide extra information to the builder to further specialize a specimen to my test. As it is now, most of the AF relies solely on runtime type to find a builder, so once I configure how to build Circle, that configuration will be used every time. – THX-1138 Jan 29 '13 at 22:48

1 Answers1

5

If you want to assign a value while creating an anonymous instance of Circle you can use the Build method:

var fixture = new Fixture();
var c = fixture
    .Build<Circle>()
    .With(x => x.Radius, 3)
    .CreateAnonymous();

However, if there's nothing special about the Radius property, why not simply assign it a value afterwards?

var fixture = new Fixture();
var c = fixture.CreateAnonymous<Circle>();
c.Radius = 3;

The latter option is much more declarative, and will enable you to use AutoFixture's xUnit.net integration to write a much terser test that removes all the accidental complexity:

[Theory, AutoData]
public void Test3(Circle c)
{
    c.Radius = 3;

    // Act and assert here
}
Mark Seemann
  • 225,310
  • 48
  • 427
  • 736
  • The original question (as I undestand it) can be rewritten to: How to create the object using seed-based AutoFixture's factory method, but using seed that is not of type of the resulting anonymous instance? Or: How we can pass additional custom parameters to our custom ISpecimenBuilder class when invoking seed-based factory methods? – sgnsajgon Oct 07 '14 at 21:37